【问题标题】:Formatting decimal places with unknown number用未知数格式化小数位
【发布时间】:2015-06-03 13:20:15
【问题描述】:

我正在打印一个我不知道其值的数字。在大多数情况下,该数字是整数或尾随 0.5。在某些情况下,数字以 0.25 或 0.75 结尾,而且数字很少达到千分位。我如何专门检测最后一种情况?现在我的代码检测到一个整数(0 个小数位),正好是 0.5(1 个小数位),然后在所有其他情况下恢复到 2 个小数点,但是当它需要时我需要转到 3。

class func getFormattedNumber(number: Float) -> NSString {

    var formattedNumber = NSString()

    // Use the absolute value so it works even if number is negative
    if (abs(number % 2) == 0) || (abs(number % 2) == 1) {  // Whole number, even or odd
        formattedNumber = NSString(format: "%.0f", number)
    }

    else if (abs(number % 2) == 0.5) || (abs(number % 2) == 1.5) {
        formattedNumber = NSString(format: "%.1f", number)
    }

    else {
        formattedNumber = NSString(format: "%.2f", number)
    }

    return formattedNumber

}

【问题讨论】:

  • 在最后一个 else 范围内试试这个:formattedNumber = NSString(format: "%.3f", number)
  • 我想实际检测这个数字是否去了 3 个地方,我不想简单地依靠那个。
  • 请注意,Float 和 Double 都不能准确表示所有小数。如果用户输入 1.23,它将(大致)存储为 1.2300000190734863。你会如何展示它? – 换句话说,“小数位数”对于二进制浮点值没有精确的含义。
  • 如果数字是 6.5,则代码正确地将余数与 0.5 匹配。如果系统在后面加上 0,那不是很多吗?
  • 6.5 可以完全表示为浮点数。大多数小数不能

标签: swift logic


【解决方案1】:

Float 使用二进制 (IEEE 754) 表示,不能表示 精确的所有小数。例如,

let x : Float = 123.456

x 中存储字节42f6e979,大约是 123.45600128173828。那么x 有 3 位还是 14 位小数位?

如果你指定了一个最大数量,你可以使用NSNumberFormatter 应显示的小数位数:

let fmt = NSNumberFormatter()
fmt.locale = NSLocale(localeIdentifier: "en_US_POSIX")
fmt.maximumFractionDigits = 3
fmt.minimumFractionDigits = 0

println(fmt.stringFromNumber(123)!)      // 123
println(fmt.stringFromNumber(123.4)!)    // 123.4
println(fmt.stringFromNumber(123.45)!)   // 123.45
println(fmt.stringFromNumber(123.456)!)  // 123.456
println(fmt.stringFromNumber(123.4567)!) // 123.457

Swift 3/4 更新:

let fmt = NumberFormatter()
fmt.locale = Locale(identifier: "en_US_POSIX")
fmt.maximumFractionDigits = 3
fmt.minimumFractionDigits = 0

print(fmt.string(for: 123.456)!) // 123.456

【讨论】:

  • 这个答案比我的好很多。
  • 太棒了,我遇到的所有答案都缺少设置语言环境,谢谢!
【解决方案2】:

您可以使用%g 来抑制尾随零。那么我认为你不需要通过确定名额的业务。例如 -

var num1:Double = 5.5
var x = String(format: "%g", num1) // "5.5"

var num2:Double = 5.75
var x = String(format: "%g", num2) // "5.75"

或指定位置数量的这种变体。例如 -

var num3:Double = 5.123456789
var x = String(format: "%.5g", num3) // "5.1235"

【讨论】:

  • 但请注意,数字 5 是 total 位数,因此 String(format: "%.5g", 51245.789) 给出 51246 没有任何小数位数,并且 %g 可以切换为指数表示,例如String(format: "%.5g", 512457.89) 给出 5.1246e+05。
【解决方案3】:

我的 2 美分 ;) Swift 3 准备好了

将浮点数四舍五入,并将尾随零去除到所需的最小/最大小数位数。

extension Double {
    func toString(minimumFractionDigits: Int = 0, maximumFractionDigits: Int = 2) -> String {
        let formatter = NumberFormatter()
        formatter.locale = Locale(identifier: "en_US_POSIX")
        formatter.minimumFractionDigits = minimumFractionDigits
        formatter.maximumFractionDigits = maximumFractionDigits

        return formatter.string(from: self as NSNumber)!
    }
}

用法:

Double(394.239).toString() // Output: 394.24
Double(394.239).toString(maximumFractionDigits: 1) // Output: 394.2

【讨论】:

    【解决方案4】:

    如果要将浮点数打印到小数点后 3 位,可以使用String(format: "%.3f")。这将四舍五入,所以0.10000001 变为0.1000.1009 变为0.101 等等。

    但听起来你不想要尾随的零,所以你可能想要修剪掉它们。 (有没有办法用format 做到这一点?编辑:是的,@simons 指出的g

    最后,这真的不应该是一个类函数,因为它是在原始类型上操作的。最好让它成为一个免费功能,或者扩展Double/Float

    extension Double {
        func toString(#decimalPlaces: Int)->String {
            return String(format: "%.\(decimalPlaces)g", self)
        }
    }
    
    let number = -0.3009
    number.toString(decimalPlaces: 3)  // -0.301
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-03-27
      • 1970-01-01
      • 1970-01-01
      • 2011-06-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多