Обычно я тот, кто входит и объясняет людям, что введенное ими число не может быть представлено как число с плавающей запятой, и где ошибки округления, бла-бла-бла.
Этот вопрос гораздо веселее, чем то, что мы обычно видим, и он точно показывает, что не так с мудростью толпы "с плавающей запятой неточно, прочитайте" , что должен знать каждый компьютерщик ..." LoLz».
36.76662445068359375
- это не просто 19-значное десятичное число. Это будет 19-значное десятичное число, которое также точно представляется в двоичной двоичной переменной с плавающей запятой. Таким образом, начальное преобразование подразумевается в:
double wtf = 36.76662445068359375000;
точно. wtf
содержит ровно b100100.11000100010000011
, и округление не произошло.
Спецификация для NSDecimalNumber говорит, что она представляет числа как десятичную мантиссу из 38 цифр и десятичную степень в диапазоне [-127,128], поэтому значение в wtf
также точно представляется в виде NSDecimalNumber. Таким образом, мы можем заключить, что numberWithDouble
не обеспечивает правильного преобразования. Хотя я не могу найти документацию, в которой утверждается, что эта процедура преобразования правильно округлена, нет веских оснований для этого не делать. Это реальная ошибка , , пожалуйста, сообщите об этом .
Я отмечаю, что средства форматирования строк в iPhoneOS, кажется, дают правильно округленные результаты, поэтому вы, вероятно, можете обойти это, сначала отформатировав double как строку с точностью до 38 цифр, а затем используя decimalNumberWithString
. Не идеально, но это может сработать для вас.