#java #ieee-754
Вопрос:
Недавно я столкнулся с проблемой, когда мне пришлось подумать о неточности представления чисел с плавающей запятой. Но, к моему удивлению, я не нашел ошибок, которые ожидал. Я создал простой пример кода для описания моего вопроса
public class Main {
public static void main(String[] args) {
float one_point_six = 1.6f; // According to IEEE-754, should be 1.60000002384185791015625
float zero_point_four = 0.4f; // According to IEEE-754, should be 0.4000000059604644775390625
float sum = one_point_six zero_point_four; // shouldn't this be 2.0000000298023223876953125?
System.out.println(Math.ceil(sum)); // Prints 2.0. Shouldn't this be 3?
System.out.println(sum > 2f); // Prints false. Why?
}
}
Результат остается неизменным, даже если я заменяю числа с плавающей запятой на удвоения. Java выполняет некоторые округления или я что-то упускаю?
Я использовал https://www.h-schmidt.net/FloatConverter/IEEE754.html для определения «фактического» значения, которое сохраняется.
Ответ №1:
разве это не должно быть 2.0000000298023223876953125?
Нет. Как вы знаете, float
имеет ограниченную точность, поэтому она недостаточно точна для хранения числа с такой точностью. Пытаясь использовать ваш конвертер и введя туда 2.0000000298023223876953125, вы обнаружите, что фактическое сохраненное значение равно всего лишь «2».
Комментарии:
1. Да, это имеет смысл. Чтобы проверить это, я изменил тип данных sum с float на double и добавил приведение к double для one_point_six при суммировании. Это дало мне результаты 3 и true. Спасибо!