2014-01-03 3 views
2

У меня есть строка, которая отформатирована правильно, чтобы быть отлитой до двойника, и она отлично работает для большинства десятичных знаков. Проблема в том, что для .33, .67 и, возможно, других, которые я не тестировал, десятичное значение становится чем-то вроде .6700000000002, или .329999999998. Я понимаю, почему это происходит, но у кого-то есть предложение исправить это.Неправильное десятичное преобразование из двоичного в строку в java

+2

Добро пожаловать в мир чисел с плавающей запятой :) –

ответ

4

Это результат правил округления IEEE-754, некоторые цифры не могут быть представлены точно в two's complement. Например, 1/10 не является точно представимым.

Вы можете добавить больше точности (но не бесконечно), используя BigDecimal.

BigDecimal oneTenth = new BigDecimal("1").divide(new BigDecimal("10")); 
System.out.println(oneTenth); 

Какие выходы 0.1

3

Некоторые десятичные числа не могут быть точно представлены с внутренним представлением машины базы 2.

+0

ах, который имел бы смысл. Значит, это связано с стандартом IEEE с плавающей запятой, который я предполагаю? Любая идея, как ее исправить – KBusc

+1

@KBusc, я считаю, что стандарт IEEE-754 фактически позволяет десятичное представление с плавающей запятой (полезно для учета и финансов). Таким образом, это действительно связано с тем, что ваша цель использует представление базы 2 (как и большинство целей). – user3146587

1

Это двойная точность для вас. Двоичные числа и десятичные знаки не работают хорошо. Если вы не делаете что-то действительно точное, это должно быть хорошо, если вы его печатаете, вы должны использовать либо десятичный формат, либо printf.

+0

хорошо посмотрев как это в java я не буду использовать printf – KBusc

+1

Java имеет печатьf. – erzr2

+0

@KBusc Вы [можете] (http://docs.oracle.com/javase/7/docs/api/java/io/PrintStream.html#printf%28java.lang.String,%20java.lang.Object .. .% 29). –

1

Значение чисел с плавающей запятой не сохраняется непосредственно, а с экспоненциальными значениями. Вы можете написать 3.1233453456356 как номер, но в памяти хранится что-то вроде 3 и 2^6. Он пытается сохранить значение как можно ближе к вашему номеру, но эти различия могут произойти.

1

Это не должно быть проблемой, если вы не испытывать равенства. С плавающей точкой тестами для равенства вам нужно разрешить «дельту», так что:

if (a == b) 

становится

if (abs(a-b) < 0.000001) 

или аналогичное малое значение дельты. Для печати ограничьте ее до двух знаков после запятой, а форматтер будет вокруг вас.

Смежные вопросы