2016-08-24 17 views
8

Z jakiegoś powodu niektóre Doubles w mojej aplikacji Swift sprawia mi problemy podczas konwersji do NSNumber, podczas gdy inne nie. Moja aplikacja musi przekonwertować liczbę podwójną z 2 miejscami dziesiętnymi (ceny) na NSNumbers, aby można je było przechowywać i pobierać za pomocą danych podstawowych. Na przykład kilka konkretnych cen, takich jak 79,99, oszacowałoby 99,98999999999999, o ile nie zostanie specjalnie sformatowane przy użyciu metody doubleName klasy NSNumber.Konwersja Double na NSNumber w Swift traci dokładność

Tutaj selectedWarranty.price = 79,99, jak pokazano na debugger

// item.price: NSNumber?  
// selectedWarranty.price: Double? 

item.price = NSNumber(double: selectedWarranty.price!) 

ja zaprogramować niektóre wypowiedzi drukowania, aby pokazać jak konwersja odrabia

Original double: 79.99 
Converted to NSNumber: 79.98999999999999 
.doubleValue Representation: 79.99 

Może ktoś wyjaśnić, czy istnieje powód, dlaczego inicjator nie może z pewnością zachować 2 miejsc po przecinku dla każdej liczby? Naprawdę chciałbym przechowywać ceny w podstawowych danych, tak jak powinny. Formatowanie za każdym razem, gdy jest wyświetlane, nie brzmi zbyt wygodnie.

UPDATE: Stary obiekt Rdzeń danych wpisać NSDecimalNumber przez model danych, 79.99 i 99.99 nie jest już problemem, ale teraz łatwiejsze problem z różnymi numerami ...

Original double: 39.99 
Converted to NSDecimalNumber: 39.99000000000001024 
+1

Czy możesz zrobić [minimalny, kompletny i weryfikowalny przykład] (http://stackoverflow.com/help/mcve)? – Alexander

+1

Użyj 'NSDecimalNumber' zamiast' NSNumber' dla waluty. – rmaddy

+0

Nie mogę odtworzyć tego problemu. http://swiftlang.ng.bluemix.net/#/repl/57bdc2590dcf4abf47da28c2 – Alexander

Odpowiedz

9

Po pierwsze,” ponownie myląc pewne terminy. 79.98999999999999 to wyższa precyzja niż 79.99 (ma dłuższy rozkład dziesiętny), ale niższa dokładność (różni się od wartości rzeczywistej).

Po drugie, numer NSNumber nie przechowuje ani 79.99 ani 79.98999999999999. Przechowuje wielkość wartości zgodnie ze standardem IEEE 754. To, co widzisz, jest prawdopodobnie konsekwencją logiki drukowania, która została użyta do przekształcenia tej wielkości w liczbę czytelną dla człowieka. W każdym razie nie powinieneś polegać na Float lub, aby przechowywać wartości z ustaloną dokładnością. Ze swej natury poświęcają precyzję, aby uzyskać większy zakres reprezentowalnych wartości.

Byłoby o wiele lepiej off przedstawiając ceny jako Int centów, lub jako NSDecimalNumber.

Proszę odnieść się do Why not use Double or Float to represent currency?

+0

Dzięki za wyjaśnienie. NSDecimalNumber wydaje się najlepsza. Moje jedyne pytanie brzmi, w jaki sposób mogę uzyskać model Core Data, aby pozwolić mi używać tego zamiast NSNumber? Nie jestem bardzo doświadczony w tej dziedzinie – joelrorseth

+0

Nie wiem, spróbuj otworzyć dla niego nowe pytanie. Jeśli uważasz, że ta odpowiedź spełnia Twoje bezpośrednie pytanie, zaznacz ją jako zaakceptowaną :) – Alexander

1

to jak podwójne działa wszędzie. Jeśli potrzebujesz tylko 2 miejsc po przecinku, rozważ użycie opcji liczba całkowita/długa zamiast dodawania punktu za drugą cyfrą, kiedy trzeba wyświetlić wartość.

Powiązane problemy