在Swift中将float显示为可变数量的小数位

时间:2016-03-11 22:33:31

标签: xcode swift

是否有一种简单的方法可以在Swift中向相关的小数位数显示float或double。

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

我可以轻松地格式化字符串,如下所示:

-I

但是,如果用户要将1mcg转换为0.001mg,则会显示为     0.0毫克

然而,要包含最多6个小数位以包含所有常见的可能性,将导致难看的丑陋UI。

是否有一种简单的方法来格式化字符串,以便包含一个float / double,它会显示到相关的小数位数/有效数字?我确定,给定时间和足够的样板代码,我可以金字塔,如果/它得到一个结果,但这是坦率的不优雅。

3 个答案:

答案 0 :(得分:1)

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
    }
}

用法:

let formatter = MyMassFormatter()
formatter.format = "0.######"

print(formatter.bestFitStringForWeightInGrams(0.000001))   // 1mcg
print(formatter.bestFitStringForWeightInGrams(0.005))      // 5mg
print(formatter.bestFitStringForWeightInGrams(2500))       // 2.5kg
print(formatter.bestFitStringForWeightInGrams(1234.5))     // 1234.5g

答案 1 :(得分:0)

使用Swift格式化为重要数据

您想要的是能够格式化为固定数量的有效数字,而不是固定数量的小数位数。解决这个问题的一个很好的快速选择是使用类扩展,用一些数学来决定根据数字的大小显示多少小数位。

下面的示例扩展了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)
            }
        }
    }
}

<强>用法

let num1 = 1234.5678
let num2 = 12.345678
let num3 = 0.0012345678
let num4 = 1234567.8

print(num1.sigFigs(6))
print(num1.sigFigs(2))
print(num2.sigFigs(6))
print(num2.sigFigs(2))
print(num3.sigFigs(6))
print(num3.sigFigs(2))
print(num4.sigFigs(6))
print(num4.sigFigs(2))

<强>输出

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

答案 2 :(得分:0)

如果我对您的理解正确,那么你是

  1. 使用Swift
  2. 与国际单位作战
  3. 试图显示浮点数
  4. 试图避免样板化和魔术数字化

应该一定使用苹果公司的Measurement,即:

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

MeasurementFormatter

一种格式化程序,可提供单位和度量的本地化表示。

MeasurementFormatter使用NumberFormatter格式化度量数量。
默认情况下,NumberFormatters的usesSignificantDigits property设置为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"