Pop quiz: представляет 1/3 в десятичном формате.
Ответ: Вы не можете;не точно.
Компьютеры считаются в двоичном формате. Есть еще много чисел, которые «не могут быть полностью представлены». Точно так же, как в десятичном вопросе, если у вас есть только маленький листок бумаги, на котором вы можете написать его, вы можете просто пойти с 0.3333333
и назвать его день, и тогда у вас будет число, которое очень близко к,но не совсем то же самое, что и 1 / 3
, поэтому компьютеры представляют дроби.
Или, подумайте об этом следующим образом: число с плавающей запятой занимает 32-битное число;double занимает 64. Существует только 2 ^ 32 (около 4 миллиардов) различных чисел, которые может представлять 32-битное значение. И все же, даже между 0 и 1 существует бесконечное количество чисел. Итак, учитывая, что существует не более 2 ^ 32 конкретных, конкретных чисел, которые «точно представлены» в виде числа с плавающей запятой, любое число, не входящее в этот благословенный набор из примерно 4 миллиардов значений, не представимо. Вместо того, чтобы просто делать ошибку, вы просто получаете в этом пуле 4 миллиарда значений, которые являются представимыми, и это самое близкое число к тому, которое вы хотели.
Кроме того, поскольку компьютеры учитываются в двоичном, а не в десятичном видеВаше чувство того, что является «представимым», а что нет, отключено. Вы можете подумать, что 1/3 - это большая проблема, но наверняка 1/10 - это легко, верно? Это просто 0.1
, и это точное представление. Ах, но десятая работает хорошо в десятичном формате. В конце концов, десятичная дробь основана на числе 10, что неудивительно. А в двоичном? половина, четвертый, восьмой, шестнадцатый: легко в двоичном. Десятый? Это так же сложно, как и третье: НЕ ПРЕДСТАВЛЯЕМЫЙ .
0,9 само по себе не является представимым числом. И все же, когда вы печатали свой поплавок, это то, что вы получили.
Причина в том, что печать поплавков / двойников - это искусство, а не наука. Учитывая, что только несколько чисел представимы, и учитывая, что эти числа не кажутся людям «естественными» из-за двоичной и десятичной дроби, вам действительно нужно добавить к числу стратегию «округления», иначе она будет выглядетьсумасшедший (никто не хочет читать 0,899999999999999999765). И это именно то, что делают System.out.println и co.
Но вы действительно должны взять под контроль функцию округления: никогда не используйте System.out.println для печати двойных и плавающих чисел. Вместо этого используйте System.out.printf("%.6f", yourDouble);
, и в этом случае ОБА будет печатать 0.9
. Поскольку в действительности ни один из них не может точно представлять 0,9, число, которое ближе всего к нему в числах с плавающей запятой (или, скорее, число, которое вы получаете, когда берете число, ближайшее к 2,0 (которое составляет 2,0), и число, ближайшее к 1,1 (что1.1), вычтите их, а затем найдите число, наиболее близкое к этому результату) - печатается как 0,9, хотя это не для чисел с плавающей запятой, и не печатает как 0,9 в двойном размере.