Why NSDecimalNumber(string:"2175613.285964774433431797660").intValue = 0
NSDecimalNumber(string:"2175613.285964774433431797660").int32Value = 2175613
NSDecimalNumber(string:"2175613.285964774433431797660").int64Value = 0
Who can help me?
Why NSDecimalNumber(string:"2175613.285964774433431797660").intValue = 0
NSDecimalNumber(string:"2175613.285964774433431797660").int32Value = 2175613
NSDecimalNumber(string:"2175613.285964774433431797660").int64Value = 0
Who can help me?
I tested in playground
let intval = NSDecimalNumber(string:"2175613,285964774433431797660").intValue
let intval2 = NSDecimalNumber(string:"2175613").intValue
let intval3 = NSDecimalNumber(string:"2175613.285964774433431797660").int32Value```
I got
0
2175613
2175613
I changed to (dot decimal vs comma)
let intval = NSDecimalNumber(string:"2175613.285964774433431797660").intValue
And got
2175613
So that may be a problem with locale ?
Nota: but when I changed back to comma, it worked, so not sure of the explanation.
**Apple M1 Mac OS Ventura 13.0 Xcode Version 14.1 (14B47b)
locale is "en_US"
let a = NSDecimalNumber(string: "2175613.285964774433431797660188672").intValue // a == 0 is true**
You can avoid confusion about the decimal separator by calling init(string:locale:), passing in a fixed locale. For example:
let enGB = Locale(identifier: "en_GB")
let d = NSDecimalNumber(string: "2175613.28", locale: enGB)
Having said that, there’s definitely something weird going on here. First, let’s deal with the Swift side of this. The Swift intValue property returns a Swift Integer, which is the size of a pointer. This means that it doesn’t call the -[NSNumber intValue] method, because that always returns a CInt, aka an Int32. Rather, it calls the -integerValue method.
Some poking around in the debugger reveals that -integerValue is implemented in the superclass, NSNumber, and it just calls -longValue and returns that. -longValue is implemented in NSDecimalNumber.
So, to investigate further I switched to Objective-C:
@import Foundation;
int main(int argc, char **argv) {
NSLocale * enGB = [NSLocale localeWithLocaleIdentifier:@"en_GB"];
NSDecimalNumber * d = [[NSDecimalNumber alloc] initWithString:@"2175613.285964774433431797660" locale:enGB];
NSLog(@"%@", d); // 2175613.285964774
NSLog(@"%f", d.doubleValue); // 2175613.285965
NSLog(@"%d", d.intValue); // 2175613
NSLog(@"%zd", d.integerValue); // 0
NSLog(@"%ld", d.longValue); // 0
return EXIT_SUCCESS;
}
This makes it clear that the Swift intValue is failing because -[NSDecimalNumber longValue] is failing. And I’ve no idea why that is. I stepped through the assembly in the debugger and it’s doing a bunch of stuff that looks kinda like the stuff you’d expect it to do, but I don’t know enough about how this type works to offer an informed opinion as to why it’s failing.
Regardless, I think it’s bugworthy. The fact that -intValue works but -longValue fails can’t be anything other than a bug, and I encourage you to file it as such. Please post your bug number, just for the record.
The workaround seems pretty straightforward: Use the int32Value property. Or use doubleValue property and truncate the fractional part.
Share and Enjoy
—
Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"
FB12643940
FB12643940 (NSDecimalNumber(string:"2175613.285964774433431797660").int64Value = 0 is wrong , int32Value is OK. )