Сбой в калькуляторе Google, может всплывать по сравнению сэто может быть возможной причиной?
-
09-06-2019 - |
Вопрос
Я сделал это просто так (так что, это не совсем вопрос, я вижу, что понижение моды уже происходит), но вместо новообретенного Google неспособность делать математика правильно (проверьте это!согласно Google 500,000,000,000,002 - 500,000,000,000,001 = 0), я решил попробовать следующее на C, чтобы немного развить теорию.
int main()
{
char* a = "399999999999999";
char* b = "399999999999998";
float da = atof(a);
float db = atof(b);
printf("%s - %s = %f\n", a, b, da-db);
a = "500000000000002";
b = "500000000000001";
da = atof(a);
db = atof(b);
printf("%s - %s = %f\n", a, b, da-db);
}
Когда вы запускаете эту программу, вы получаете следующее
399999999999999 - 399999999999998 = 0.000000
500000000000002 - 500000000000001 = 0.000000
Казалось бы, Google использует простую 32-битную точность с плавающей запятой (ошибка здесь), если вы переключите float на double в приведенном выше коде, вы устраните проблему!Может ли это быть оно?
/мп
Решение
в C # попробуйте (double.maxvalue == (double.maxvalue - 100)), вы получите true ...
но так оно и должно быть:
http://en.wikipedia.org/wiki/Floating_point#Accuracy_problems
думая об этом, у вас есть 64 бита, представляющие число, большее 2 ^ 64 (double.maxvalue), поэтому ожидается неточность.
Другие советы
Подробнее о подобных глупостях читайте в этой замечательной статье, относящейся к калькулятору Windows.
Когда вы меняете внутренности, никто этого не замечает
Внутренности Calc - арифметический движок - были полностью выброшены и переписаны с нуля. Стандартная библиотека IEEE с плавающей запятой была заменена на библиотеку арифметики произвольной точности .Это было сделано после того, как люди продолжали писать ха-ха статьи о том, что Calc не может выполнять десятичную арифметику правильно, что, например, вычисления 10.21 - 10.2 привели к 0.0100000000000016.
Казалось бы, Google использует простую 32-битную точность с плавающей запятой (ошибка здесь), если вы переключите float на double в приведенном выше коде, вы устраните проблему!Может ли это быть оно?
Нет, вы просто откладываете решение этого вопроса.двойники по-прежнему демонстрируют ту же проблему, только с большими числами.
@ebel
думая об этом, у вас есть 64 бита, представляющие число, большее 2 ^ 64 (double.maxvalue), поэтому ожидается неточность.
2^64 - это не максимальное значение double.2^ 64 - это количество уникальных значений, которые может содержать double (или любой другой 64-разрядный тип). Double.MaxValue
равно 1.79769313486232e308.
Неточность с числами с плавающей запятой возникает не из-за представления значений, превышающих Double.MaxValue
(что невозможно, исключая Double.PositiveInfinity
).Это связано с тем фактом, что желаемый диапазон значений просто слишком велик, чтобы вписаться в тип данных.Таким образом, мы отказываемся от точности в обмен на большую эффективную дальность действия.По сути, мы отбрасываем значащие цифры в обмен на больший диапазон показателей.
@DrPizza
Даже не;кодировки IEEE используют несколько кодировок для одних и тех же значений.В частности, NaN представлен показателем всех битов-1, а затем любым ненулевым значением для мантиссы.Таким образом, существует 252 NAN для парного разряда, 223 NAN для одиночного.
Верно.Я не учитывал повторяющиеся кодировки.На самом деле их 252-1 NaNs для парных и 223хотя для одиночек -1 NaNs.:p
2^64 - это не максимальное значение double.2^ 64 - это количество уникальных значений, которые может содержать double (или любой другой 64-разрядный тип).Double.MaxValue равно 1.79769313486232e308.
Даже не;кодировки IEEE используют несколько кодировок для одних и тех же значений.В частности, NaN представлен показателем всех битов-1, а затем Любой ненулевое значение для мантиссы.Таким образом, существует 252 NANS для парного разряда, 223 NANS для одиночек.
Верно.Я не учитывал повторяющиеся кодировки.Однако на самом деле существует 252-1 NAN для парного разряда и 223-1 NAN для одиночного.:p
Дох, забыл вычесть бесконечности.
Приблизительная версия этой проблемы, которую я узнал, заключается в том, что 32-разрядные числа с плавающей запятой дают вам 5 цифр точности, а 64-разрядные числа с плавающей запятой дают вам 15 цифр точности.Это, конечно, будет варьироваться в зависимости от того, как кодируются значения с плавающей точкой, но это довольно хорошая отправная точка.