2017-02-04 20 views
5

Konwertuję liczby na czyste angielskie słowa, a ja natknąłem się na bardzo dziwne sytuacje: NSNumberFormatter ma dziwne wyjście, mniejsze niż pożądany wynik , ale liczba przyjęta jako parametr nie powoduje przepełnienia.NSNumberFormatter.string (from:) maximum possible Przekroczona wartość nie powoduje przepełnienia - Swift

Mam następujący kod:

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

i to drukuje eighteen quadrillion fourteen trillion three hundred ninety-eight billion five hundred nine million four hundred eighty-one thousand nine hundred eighty-four, który jest odpowiednikiem 18014398509481984 < 999999999999999999. Jeśli próbuję uzyskać słowa od 18014398509481984, wynik jest tym, którego oczekiwałem, ciągiem opisanym powyżej. Jednakże, jeśli dodam jeszcze jeden 9 do 999.., to wywala z komunikatem:

całkowitą dosłowne 9999999999999999999 przelewy, gdy przechowywany w Int

Oto Swift Sandbox Test, aby uczynić pytanie bardziej zrozumiały.


Moje rzeczywiste pytanie brzmi: Zakładając, że wyjście pierwszego Spróbuj: 180140398509481984 jest jakaś granica dla numberFormatter.string(from:), dlaczego nie 999999999999999999 spowodować przepełnienie, ale po prostu wyświetla ten limit, a 9999999999999999999 (z dodatkowe 9) powoduje przepełnienie?

+1

Dziwne. Nawet jeśli użyjesz '180140398509481985', nadal otrzymasz' 180140398509481984' kiedy jest napisane. – rmaddy

+1

To także dziwny limit. Jest między 2^57 i 2^58. – rmaddy

+0

@rmaddy to jest dokładnie to, o co proszę. Czy jest to jakiś limit tylko dla tej funkcji, czy jest to problem z maksymalną wartością Int/NSNumber? –

Odpowiedz

4

9_999_999_999_999_999_999 powoduje Int przepełnienia, ponieważ jest większa niż Int64.max jest 9_223_372_036_854_775_807 (tj 0x7fffffffffffffff).

o przyczynach liczba formater jest zatykania się w 18_014_398_509_481_984 (to znaczy, 2 , 0x40000000000000) dla .spelledOut, wydaje się podejrzanie jak błąd wynikający z 64-bitowych representions zmiennoprzecinkowych w wartościach. Nie możemy być pewni bez przechodzenia przez źródło dla NSNumberFormatter i NSNumber w niektórych szczegółach, ale sugeruję to, ponieważ górny sufit jest tu, przypadkowo, dokładnie podwójną największą wartością całkowitą, którą 64-bitowy typ zmiennoprzecinkowy może przechwycić wiernie.

+0

Nie zauważyłem, że ... dzięki –

+1

Fundacja i podstawowa fundacja są otwarte.Funkcja ['CFNumberFormatterCreateStringWithNumber'] (https://github.com/apple/swift-corelibs-foundation/blob/173e9ea16cf1a0ed9b21cc11ea8a2d15b3f8dca9/CoreFoundation/Locale.subproj/CFNumberFormatter.c) ma nawet ostrzegawcze ostrzeżenie, że" Wartości CFNumbers z duże, niepodpisane 64-bitowe ints nie przetrwają zbyt dobrze ". Wygląda na to, że Apple już wie o tym problemie. –