Is there a simple way of displaying a float or double to a relevant number of decimal places in Swift.
是否有一种简单的方法可以在Swift中显示一个float或double到相关的小数位数。
For example, an iOS app using SI units, which can be altered depending on the property desired, and converted through up to 6 orders of magnitude depending on desired inputs and output. Therefore it needs to display not only 1mg to 1000 micrograms, but also the other way around - i.e 1 microgram = 0.001 mg.
例如,使用SI单位的iOS应用程序,可根据所需属性进行更改,并根据所需的输入和输出进行最多6个数量级的转换。因此,它不仅需要显示1mg至1000微克,而且还需要显示相反的方式 - 即1微克= 0.001毫克。
I can easily format a string as follows:
我可以轻松地格式化字符串,如下所示:
textFieldFoo.text = NSString(format: "%.1f mg", bar) as String
However, if the user were to convert from 1mcg to 0.001mg, this would display as 0.0 mg
但是,如果用户将1mcg转换为0.001mg,则显示为0.0 mg
Yet, to include up to 6 decimal places to encompass all common possibilities would lead to an unwieldy, ugly looking UI.
然而,要包含最多6个小数位以包含所有常见的可能性将导致难看的丑陋UI。
Is there a simple way to format a string, in order to include a float/ double where it is displayed to a relevant number of decimal places/ significant figures? I'm sure, given time and enough boilerplate code, that I could pyramid if/ else it to get a result, but that's frankly inelegant.
是否有一种简单的方法来格式化字符串,以便包含一个float / double,它显示到相关的小数位数/有效数字?我敢肯定,鉴于时间和足够的样板代码,我可以金字塔,如果/它得到一个结果,但这是坦率地不优雅。
2 个解决方案
#1
1
There's NSMAssFormatter
but it doesn't go all the way down to microgram. It was designed to format human-level weight.
有NSMAssFormatter,但它不会一直到微克。它旨在形成人类体重的格式。
You can roll your own by subclassing NSNumberFormatter
:
你可以通过继承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
}
}
Usage:
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
#2
0
Formatting to Significant Figures using Swift
使用Swift格式化为重要数字
What you want is the ability to format to a fixed number of significant figures, rather than a fixed number of decimal places. A good swift option to solve this is using class extensions, with a little maths to decide how many decimal places to show based on the magnitude of the number.
你想要的是能够格式化为固定数量的有效数字,而不是固定的小数位数。解决这个问题的一个很好的快速选择是使用类扩展,用一些数学来决定根据数字的大小显示多少个小数位。
The example below extends the Double class to enable formatting to a fixed number of significant figures and uses either float notation or scientific notation depending on the magnitude of the number.
下面的示例扩展了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)
}
}
}
}
Usage
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))
Output
1234.57
1.2e+03
12.3457
12
0.001235
1.2e-03
1.23457e+06
1.2e+06
#1
1
There's NSMAssFormatter
but it doesn't go all the way down to microgram. It was designed to format human-level weight.
有NSMAssFormatter,但它不会一直到微克。它旨在形成人类体重的格式。
You can roll your own by subclassing NSNumberFormatter
:
你可以通过继承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
}
}
Usage:
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
#2
0
Formatting to Significant Figures using Swift
使用Swift格式化为重要数字
What you want is the ability to format to a fixed number of significant figures, rather than a fixed number of decimal places. A good swift option to solve this is using class extensions, with a little maths to decide how many decimal places to show based on the magnitude of the number.
你想要的是能够格式化为固定数量的有效数字,而不是固定的小数位数。解决这个问题的一个很好的快速选择是使用类扩展,用一些数学来决定根据数字的大小显示多少个小数位。
The example below extends the Double class to enable formatting to a fixed number of significant figures and uses either float notation or scientific notation depending on the magnitude of the number.
下面的示例扩展了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)
}
}
}
}
Usage
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))
Output
1234.57
1.2e+03
12.3457
12
0.001235
1.2e-03
1.23457e+06
1.2e+06