Xcode 在Swift中显示小数位数可变的浮点

Xcode 在Swift中显示小数位数可变的浮点,xcode,swift,Xcode,Swift,是否有一种简单的方法可以在Swift中显示相应小数位数的浮点或双精度 例如,使用SI单位的iOS应用程序,可以根据所需的属性进行更改,并根据所需的输入和输出转换多达6个数量级。因此,它不仅需要显示1mg到1000微克,还需要显示另一种方式,即1微克=0.001毫克 我可以很容易地将字符串格式化如下: textFieldFoo.text = NSString(format: "%.1f mg", bar) as String 但是,如果用户要从1mcg转换为0.001mg,则显示为 0.0毫克

是否有一种简单的方法可以在Swift中显示相应小数位数的浮点或双精度

例如,使用SI单位的iOS应用程序,可以根据所需的属性进行更改,并根据所需的输入和输出转换多达6个数量级。因此,它不仅需要显示1mg到1000微克,还需要显示另一种方式,即1微克=0.001毫克

我可以很容易地将字符串格式化如下:

textFieldFoo.text = NSString(format: "%.1f mg", bar) as String
但是,如果用户要从1mcg转换为0.001mg,则显示为 0.0毫克

然而,包含最多6位小数以包含所有常见的可能性将导致一个笨拙、难看的UI


是否有一种简单的方法来格式化字符串,以便在其中包含浮点数/双精度数,并将其显示为相关的小数位数/有效数字?我敢肯定,如果有足够的时间和样板代码,我可以将if/else进行金字塔化以获得结果,但坦率地说,这并不雅观。

NSMAssFormatter
,但它不会一直下降到微克。它被设计成人体水平重量的格式

您可以通过子类化
NSNumberFormatter
来实现自己的滚动:

enum MassUnit: Double {
    case Microgram = 1e-6
    case Milligram = 1e-3
    case Gram = 1
    case Kilogram = 1e3

    static let allUnits: [MassUnit] = [.Microgram, .Milligram, .Gram, .Kilogram]

    var unitAbbreviation: String {
        get {
            switch self {
            case .Microgram: return "mcg"
            case .Milligram: return "mg"
            case .Gram: return "g"
            case .Kilogram: return "kg"
            }

        }
    }
}

class MyMassFormatter: NSNumberFormatter {
    func bestFitStringForWeightInGrams(weight: Double) -> String {
        var selectedString = self.stringFromNumber(weight)!
        var selectedUnit = MassUnit.Gram

        // Pick the unit that results in the shortest string
        for unit in MassUnit.allUnits {
            if let str = self.stringFromNumber(weight / unit.rawValue)
                where str.characters.count < selectedString.characters.count {
                    selectedString = str
                    selectedUnit = unit
            }
        }

        return selectedString + selectedUnit.unitAbbreviation
    }
}

使用Swift格式化为有效数字

1234.57
1.2e+03
12.3457
12
0.001235
1.2e-03
1.23457e+06
1.2e+06
您需要的是能够格式化为固定数量的有效数字,而不是固定数量的小数位数。解决这个问题的一个很好的swift方法是使用类扩展,再加上一点数学知识,根据数字的大小来决定要显示多少个小数位

import Foundation

//extension to format a Double to a fixed number of significant figures
extension Double {
    func sigFigs(_ numberOfSignificantFigures: Int) -> String {

        let mag = log10(abs(self))
        let intMag = Int(mag)

        if mag >= 0 {
            if intMag < numberOfSignificantFigures {
                return String(format: "%.\(numberOfSignificantFigures - intMag - 1)f",self)
            }
            else {
                return String(format: "%.\(numberOfSignificantFigures - 1)e",self)
            }
        }
        else {
            if -intMag < numberOfSignificantFigures {
                return String(format: "%.\(numberOfSignificantFigures)f",self)
            }
            else {
                return String(format: "%.\(numberOfSignificantFigures - 1)e",self)
            }
        }
    }
}
下面的示例扩展了Double类,以允许将格式设置为固定数量的有效数字,并根据数字的大小使用浮点表示法或科学表示法

import Foundation

//extension to format a Double to a fixed number of significant figures
extension Double {
    func sigFigs(_ numberOfSignificantFigures: Int) -> String {

        let mag = log10(abs(self))
        let intMag = Int(mag)

        if mag >= 0 {
            if intMag < numberOfSignificantFigures {
                return String(format: "%.\(numberOfSignificantFigures - intMag - 1)f",self)
            }
            else {
                return String(format: "%.\(numberOfSignificantFigures - 1)e",self)
            }
        }
        else {
            if -intMag < numberOfSignificantFigures {
                return String(format: "%.\(numberOfSignificantFigures)f",self)
            }
            else {
                return String(format: "%.\(numberOfSignificantFigures - 1)e",self)
            }
        }
    }
}
输出

1234.57
1.2e+03
12.3457
12
0.001235
1.2e-03
1.23457e+06
1.2e+06

如果我理解正确,您是:

  • 使用Swift
  • 使用国际单位制
  • 试图显示浮点
  • 尽量避免使用陈词滥调和可能的神奇数字
  • 你一定要用苹果的,它是:

    标有度量单位的数字量,支持单位转换和单位感知计算

    这就是:

    提供单位和度量的本地化表示的格式化程序

    MeasurementFormatter使用格式设置度量的数量。
    默认情况下,NumberFormatters设置为false,但:

    将此属性设置为true,以根据minimumSignificantDigits和maximumSignificantDigits属性指定的有效数字配置格式化数字。默认情况下,最小有效位数为1,最大有效位数为6

    下面是一个关于如何处理体量的示例

    let micrograms = Measurement(value: 1, unit: UnitMass.micrograms) // 1.0 µg
    let nanograms = micrograms.converted(to: .nanograms) // 1000.0000000000001 ng
    let picograms = micrograms.converted(to: .picograms) // 1000000.0 pg
    let milligrams = micrograms.converted(to: .milligrams) // 0.001 mg
    let centigrams = micrograms.converted(to: .centigrams) // 0.0001 cg
    let decigrams = micrograms.converted(to: .decigrams) // 1e-05 dg
    let grams = micrograms.converted(to: .grams) // 1e-06 g
    let kilograms = micrograms.converted(to: .kilograms) // 1e-09 kg
    let ounces = micrograms.converted(to: .ounces) // 3.527399072294044e-08 oz
    let pounds = micrograms.converted(to: .pounds) // 2.2046244201837776e-09 lb
    let stones = micrograms.converted(to: .stones) // 1.574731232746851e-10 st
    
    let formatter = MeasurementFormatter()
    formatter.numberFormatter.usesSignificantDigits = true
    formatter.unitOptions = .providedUnit
    
    formatter.string(from: nanograms) // "1 000 ng"
    formatter.string(from: picograms) // "1 000 000 pg"
    formatter.string(from: micrograms) // "1 µg"
    formatter.string(from: milligrams) // "0,001 mg"
    formatter.string(from: centigrams) // "0,0001 cg"
    formatter.string(from: decigrams) // "0,00001 dg"
    formatter.string(from: grams) // "0,000001 g"
    formatter.string(from: kilograms) // "0,000000001 kg"
    formatter.string(from: ounces) // "0,000000035274 oz"
    formatter.string(from: pounds) // "0,00000000220462 lb"
    formatter.string(from: stones) // "0,000000000157473 st"
    
    

    也许您可以为此使用
    NSNumberFormatter
    。但是如果你有nano,micro和其他前缀,我想你需要一个自定义的格式化实现。谢谢。在接下来的一两天里,我将尝试让它发挥作用,马克回答说,如果它起作用,我认为这不会回答问题,因为他们事先不知道有效数字的数量。用户输入float/double,他们希望在显示器上显示看起来不错的最大sig数字。不多也不少。