2015-08-25 3 views
2

Недавно я придумал небольшую проблему в ios swift при преобразовании Double to Int.Strange Convertion double to int

var myDoubleValue: Double = 10.2 
var newInt = Int(myDoubleValue * 100) //1019 

Там я умножая 10.2 на 100 и не получить ожидаемого значения (1020) и вместо 1019 ...

Но работает правильно в большинстве случаев следующим

var myDoubleValue: Double = 10.3 
var newInt = Int(myDoubleValue * 100) //1030 

Кроме того, я также проверил его с Java и тем же вопросом там.

double myDoubleValue = 10.2; 
int myIntValue1 = (int)(myDoubleValue * 100); //1019 

Я мог бы преодолеть Проблема при выполнении «круглого», прежде чем обращенный к Int следующим ...

var myDoubleValue: Double = 10.2 
var newInt = Int(round(myDoubleValue * 100)) //1020 

Но это идет к чему-то я не хочу, если значение с 3 знаками после запятой, как следует, потому что это округление в то время (10,206 ---> 1021)

+1

Во-первых, отображаемое значение как раз то, что не все значения, используйте форматирование, чтобы увидеть больше цифр. Во-вторых, 10.2 или 10.3 не могут быть точно представлены в номере с плавающей запятой base2, поэтому результаты могут быть очень немного отличающимися от ожидаемых. В-третьих, это может помочь, если вы потратили некоторое время на изучение чисел с плавающей запятой. – zaph

+3

Сильно связано: [Является ли математика с плавающей запятой?] (Http://stackoverflow.com/questions/588004/is-floating-point-math-broken) –

ответ

2

Отображение значения только что, не все значения, использовать форматирование, чтобы увидеть больше цифр. 10.2 или 10.3 не могут быть точно представлены в номере с плавающей запятой base2, поэтому результаты могут быть немного отличающимися от ожидаемых.

Вот пример, который показывает, что происходит:

var myDoubleValue1: Double = 10.2 
print(String(format: "myDoubleValue1: %.17f", myDoubleValue1)) 
// myDoubleValue1: 10.19999999999999929 

var myDoubleValue2: Double = 10.3 
print(String(format: "myDoubleValue2: %.17f", myDoubleValue2)) 
// myDoubleValue2: 10.30000000000000071 

Обратите внимание, что 10,2 обращенные к плавающей точкой двойной, как слегка ниже 10,2 и будет обрезано вниз.

Следует отметить, что 10.3 обращенные к плавающей точкой Двойной виде слегка выше 10.3 и волю не быть усечены вниз.

Если точная десятичной математике, например, в калькуляторе или при работе с деньгами, требуется использование NSDecimalNumber

1

Java ответ

Это происходит потому, что double и float типы и оберток не гарантируют точные значения при работе на.

В Java рекомендуется идиома для того, что вы ищете это:

BigDecimal myDoubleValue = new BigDecimal("10.2"); 
int myInt = myDoubleValue.multiply(new BigDecimal("100")).intValue(); 
System.out.println(myInt); 

Выход

1020 
+1

В Swift и Objective-C существует класс NSDecimalNumber, который обрабатывает десятичные числа точно. – zaph

+0

@zaph спасибо за комментарий. Я почти ничего не знаю о Objective-C/Swift, поэтому я не мог ответить на эту часть :) – Mena

2

Это является результатом ошибок облавы/усечения. На самом деле,

myDoubleValue = 10.2 

что-то вроде

myDoubleValue = 10.1999999999999 

так

myDoubleValue * 100 = 1019.999999999 

и после того, как отделан к int у вас есть 1019. Лучше практика заключается в раунд до, а не отделки:

double myDoubleValue = 10.2; 
int myIntValue1 = (int)(myDoubleValue * 100 + 0.5); // note "+ 0.5" 
System.out.println(myIntValue1); 
0

Похоже, что вы хотите, чтобы округлить небольшое количество ошибок, но вы хотите, чтобы округлить другие мудрыми.

Вы можете сделать это

double d = 10.199999; 
long l = (long) (d * 100 + 0.01); // l = 10.20 

double d = 10.206; 
long l = (long) (d * 100 + 0.01); // l = 10.20