Zero symbol in iOS MeasurementFormatter - ios

I'm having problems to declare/use a zero symbol for an unknown value when using MeasurementFormatter:
let numberFormatter = NumberFormatter()
numberFormatter.numberStyle = .decimal
numberFormatter.zeroSymbol = "?"
numberFormatter.string(from: 0.0) // '?'
let formatter = MeasurementFormatter()
formatter.unitOptions = .providedUnit
formatter.numberFormatter = numberFormatter
var distance = Measurement<UnitLength>(value: 0, unit: .parsecs)
formatter.string(from: distance) // '0 pc' - expected: '? pc'
Trying different declarations of the value such as Double.zero doesn't change the output.
Is this a conceptual thing in iOS or am I missing something here?

It turned out to produce the desired output by changing the Measurement declaration (distance):
let dist1 = Measurement<UnitLength>(value: 0, unit: .parsecs) // output: '0 pc'
let dist2 = Measurement(value: 0, unit: Unit(symbol: UnitLength.parsecs.symbol)) // output '? pc' as expected
A radar is filed.

Related

NumberFormatter Fraction Digits confusion (swift)

I am trying to format numbers so that there are always 4 digits after the decimal place. For example:
1 // 1.0000
0 // 0.0000
1.23 // 1.2300
1.234 // 1.2340
1.2345 // 1.2345
1.23456 // 1.2346 **[edited]**
I have tried all kinds of combinations of the following:
let formatter = NumberFormatter()
formatter.usesSignificantDigits = true // I believe this the default so not required
formatter.numberStyle = .decimal
formatter.maximumSignificantDigits = 4
formatter.minimumSignificantDigits = 4
formatter.maximumFractionDigits = 4
formatter.minimumFractionDigits = 4
let p = formatter.string(from: NSNumber(value: percentage))
debugPrint("p = \(p)")
But in two of the cases, this is what I get:
0 // 0.000
0.0123456 // 0.01234
Here is an example:
and the debug output:
"p = 0.9375"
"p = 0.000"
"p = 0.03125"
"p = 0.000"
"p = 0.03125"
What am I missing?
[I thought I had seen really good explanation in here some time ago, but can no longer find it - if anyone could drop a link to it, that would be great too!]
If you are trying to dictate the number of decimal places, then simply remove this significant digits stuff:
let formatter = NumberFormatter()
formatter.numberStyle = .decimal
formatter.maximumFractionDigits = 4
formatter.minimumFractionDigits = 4
let values: [Double] = [
1, // 1.0000
0, // 0.0000
1.23, // 1.2300
1.234, // 1.2340
1.2345, // 1.2345
1.23456 // 1.2346 ... if you really want 1.2345, then change formatter’s `roundingMode` to `.down`.
]
let strings = values.map { formatter.string(for: $0) }
That yields the four digits after the decimal point, as desired.

Swift rounding to X decimals places issue when .999999

I did try different rounding to decimal places methods and all of them have the same in common. When I use a number, lets say 0.99999 and I want to round it to 2 decimal places. My expected result would be 0.99 but instead I get 1.00
I did try
let divisor = pow(10.0, Double(decimals))
let roundedVal = round(value * divisor) / divisor
Also did try
String(format:"%.2f",decimals)
And
let behavior = NSDecimalNumberHandler(roundingMode: .plain, scale: decimals, raiseOnExactness: false, raiseOnOverflow: false, raiseOnUnderflow: false, raiseOnDivideByZero: true)
NSDecimalNumber(value: value).rounding(accordingToBehavior: behavior)
let roundedValue2 = NSDecimalNumber(value: 0.6849).rounding(accordingToBehavior: behavior)
All methods give me the same issue.
Some ideas?
Thanks for the help!
EDIT:
The idea is that rounding is okay for all cases but not okay for that 0.9999 case. The display numbers are small always (range from 0.000 to 1) and decimals to show is parameter so 0.348 should be 0.35 and not 0.34 (when trunked)
let amount = 0.99999999999999
let formatter = NumberFormatter()
formatter.numberStyle = .decimal
formatter.maximumFractionDigits = 2
formatter.roundingMode = .floor // rounding mode floor is the key here
let formattedAmount = formatter.string(from: amount as NSNumber)!
print(formattedAmount) // 0.99

Dividing massive numbers in Swift

I have a UInt128 holding a massive number like 2000009100000000000000 and I want to divide it by 1/10^30
How do I do that?
Possibly by using NSDecimalNumber. For example,
let num1 = NSDecimalNumber(string: "2000009100000000000000")
let num2 = NSDecimalNumber(mantissa: 10, exponent: 30, isNegative: false)
let result = num1.dividing(by: num2)

Placing spaces in a String with varying length

So I have a Double that gets calculated and varies in length each time (based on certain input). This Double is placed in to a String.
var doubleNumber = 30440.8734
var string = "€ \(round(100 * doubleNumber) / 100)"
var numberString: String = string.stringByReplacingOccurrencesOfString("€ ", withString: "", options: NSStringCompareOptions.LiteralSearch, range: nil)
var splitString = split(numberString) {$0 == "."}
println(splitString[0])
Result would be: "30440"
What I would like to do is to place spaces in this number for readability. For which the result would end in: "30 440"
Any suggestions?
Regardless of the issue of currency formats, you can use an NSNumberFormatter to add spaces as grouping separators in a number:
var doubleNumber = 30440.8734
let numberFormatter = NSNumberFormatter()
numberFormatter.numberStyle = .CurrencyStyle
numberFormatter.currencySymbol = "€ "
numberFormatter.currencyGroupingSeparator = " "
numberFormatter.maximumFractionDigits = 0
if let formattedString = numberFormatter.stringFromNumber(doubleNumber) {
println(formattedString)
}
Output: € 30 441
I do think that NSNumberFormatter approach is better:
let f = NSNumberFormatter()
f.groupingSeparator = " "
f.groupingSize = 3
f.usesGroupingSeparator = true
f.stringFromNumber("30456".toInt()!)
but here's my solution if I would do this task without formatter:
var i: Int = count(number)
let a = "".join(map(number) {String($0) + (--i % 3 == 0 ? " " : "")})
a.stringByTrimmingCharactersInSet(NSCharacterSet.whitespaceCharacterSet())

CGFloat to NSString with decimal only if there is fractional part

Not sure how to word the title correctly... but what I am wondering is if there is some clever format specifier that will take the number 4.5 and give me #"4.5" but also take the number 2 and give me #"2".
Using the %.1f specifier gives me #"4.5" but also #"2.0". I am trying to get rid of the ".0" bit.
Does such a beast exist, or am I going to have to do some math on this? FWIW, I am trying to iterate over an array of values ranging from 0 to 5 increasing in half-steps, so 0, 0.5, 1, 1.5, ..., 4.5, 5
Cheers!
NSNumberFormatter is a good choice here. You can configure it to not show the fractional digits if the number is an integer. For example:
NSArray *numbers = #[#0, #0.5, #1.0, #1.5, #2.0, #2.5];
NSNumberFormatter *numberFormatter = [[NSNumberFormatter alloc] init];
numberFormatter.alwaysShowsDecimalSeparator = NO;
numberFormatter.minimumFractionDigits = 0;
numberFormatter.maximumFractionDigits = 1;
numberFormatter.minimumIntegerDigits = 1;
for (NSNumber *number in numbers) {
NSLog(#"%#", [numberFormatter stringFromNumber:number]);
}
Output:
>> 0
>> 0.5
>> 1
>> 1.5
>> 2
>> 2.5
This is even easier (Swift):
let num1: Double = 5
let num2: Double = 5.52
let numberFormatter = NSNumberFormatter()
numberFormatter.numberStyle = .DecimalStyle
print(numberFormatter.stringFromNumber(NSNumber(double: num1)))
print(numberFormatter.stringFromNumber(NSNumber(double: num2)))
This will print 5 and then 5.52.

Resources