Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

NSNumberFormatter.string(from: ) maximum possible Value exceeded does not result in Overflow - Swift

Tags:

I am converting numbers to pure English words, and I ran into some very odd situations: NSNumberFormatter has a strange output, smaller than the desired result, but the number taken as parameter doesn't cause an overflow.

I have the following code:

 import Foundation
 var numberFormatter: NumberFormatter = NumberFormatter()
 numberFormatter.numberStyle = .spellOut
 var result: String?
 result = numberFormatter.string(from: 999999999999999999)
 print(result ?? "nil")

and this prints eighteen quadrillion fourteen trillion three hundred ninety-eight billion five hundred nine million four hundred eighty-one thousand nine hundred eighty-four, which is the equivalent of 18014398509481984< 999999999999999999. If I try to get the words from 18014398509481984, the result is the one I expected, the string described above. However, if I add one more 9 to 999.., it crashes with the message:

integer literal 9999999999999999999 overflows when stored into Int

Here is a Swift Sandbox Test, in order to make the question more understandable.


My actual question is: Assuming that the output of the first try: 180140398509481984 is some kind of limit for numberFormatter.string(from:), why does 999999999999999999 not result in Overflow, but just displays that limit, and 9999999999999999999 (with an extra 9) results in Overflow?

like image 374
Mr. Xcoder Avatar asked Feb 04 '17 21:02

Mr. Xcoder


1 Answers

The 9_999_999_999_999_999_999 causes an Int overflow because it is larger than Int64.max is 9_223_372_036_854_775_807 (i.e. 0x7fffffffffffffff).

Regarding why number formatter is capping out at 18_014_398_509_481_984 (i.e., 254, 0x40000000000000) for .spelledOut, that seems suspiciously like a bug stemming from 64-bit floating point representions of the value. We can't be sure without going through the source for NSNumberFormatter and NSNumber in some detail, but I suggest this because the upper ceiling here is, coincidentally, precisely double the largest integer value that a 64-bit floating point type can capture faithfully.

like image 185
Rob Avatar answered Sep 25 '22 10:09

Rob