В моем курсе по информатике мы изучаем числа с плавающей запятой и то, как они представлены в памяти. Я уже понимаю, как они представлены в памяти (мантисса/значимость, экспонента и его предвзятость и знаковый бит), и я понимаю, как добавляются и вычитаются поплавки друг от друга (денормализация и все эти забавные вещи). Однако, изучая некоторые вопросы изучения, я заметил то, что я не могу объяснить.Точность добавления плавающих чисел против умножения Float на Integer
Когда поплавок, который не может быть точно представлен, добавляется к нему несколько раз, ответ ниже, чем мы математически ожидаем, но когда тот же самый поплавок умножается на целое число, ответ получается точно до правильного числа ,
Вот пример из нашего исследования вопросов (пример написан на Java, и я редактировал его для простоты):
float max = 10.0f; /* Defined outside the function in the original code */
float min = 1.0f; /* Defined outside the function in the original code */
int count = 10; /* Passed to the function in the original code */
float width = (max - min)/count;
float p = min + (width * count);
В этом примере, мы сказали, что результат выходит точно 10.0
. Однако, если мы посмотрим на эту проблему в виде суммы поплавков, мы получаем несколько иной результат:
float max = 10.0f; /* Defined outside the function in the original code */
float min = 1.0f; /* Defined outside the function in the original code */
int count = 10; /* Passed to the function in the original code */
float width = (max - min)/count;
for(float p=min; p <= max; p += width){
System.out.printf("%f%n", p);
}
Мы сказали, что окончательное значение p
в этом тесте ~9.999999
с разницей -9.536743E-7
между последним значение p
и значение max
. С логической точки зрения (зная, как работают поплавки) это значение имеет смысл.
Однако, я не понимаю, почему мы получаем ровно 10,0 для первого примера. Математически, имеет смысл, что мы получим 10.0, но зная, как поплавки хранятся в памяти, для меня это не имеет смысла. Может ли кто-нибудь объяснить, почему мы получаем точное и точное значение, умножая неточное значение float на int?
EDIT: Чтобы уточнить, в исходных вопросах исследования некоторые значения передаются функции, а другие объявлены вне функции. Мои примеры кода - это сокращенные и упрощенные версии примеров вопросов исследования. Поскольку некоторые из значений передаются в функцию, а не явно определяются как константы, я считаю, что упрощение/оптимизация во время компиляции можно исключить.
Поскольку компилятор уменьшил все это до постоянного значения. Попробуйте сделать каждый оператор функцией и вызвать один за другим. – Amit
@ Признаюсь, мои извинения, я должен был это ясно понять в моем вопросе. Некоторые из значений, определенных в примерах, передаются как переменные в функцию, которая вычисляет конечный результат, поэтому маловероятно, что это будет оптимизация компилятора. Я пытался упростить код для этого сообщения, поэтому я определил значения в примерах. Я скоро сделаю редактирование, чтобы уточнить это. – SpencerD
Если вы не собираетесь удивить меня своим редактированием, мой комментарий (если вы хотите, я отправлю его в качестве ответа) все равно будет держать. Компилятор оптимизирует все операторы до значения 'max', потому что все операторы выполняют вычисления взад и вперед. – Amit