Сбой в калькуляторе Google, может ли плавающая или двойная причина быть возможной причиной?

Я сделал это просто для удовольствия (так что, не совсем вопрос, я уже вижу, что даунмоддинг уже происходит), но вместо новообретенного Google неспособность, чтобы сделать математикаправильно (проверьте это! Согласно google 5000000000002 - 5000000000000001 = 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 в приведенном выше коде, вы решите проблему! Может ли это быть?

/ мп

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
5
0
2 374
7
Перейти к ответу Данный вопрос помечен как решенный

Ответы 7

Чтобы узнать больше о подобной глупости, прочтите эту хорошую статью, относящуюся к калькулятору Windows.

Когда вы меняете внутренности, никто не замечает

The innards of Calc - the arithmetic engine - was completely thrown away and rewritten from scratch. The standard IEEE floating point library was replaced with an arbitrary-precision arithmetic library. This was done after people kept writing ha-ha articles about how Calc couldn't do decimal arithmetic correctly, that for example computing 10.21 - 10.2 resulted in 0.0100000000000016.

It would seem like Google is using simple 32 bit floating precision (the error here), if you switch float for double in the above code, you fix the issue! Could this be it?

Нет, просто отложите вопрос. двойники по-прежнему демонстрируют ту же проблему, только с большими числами.

Ответ принят как подходящий

в C# попробуйте (double.maxvalue == (double.maxvalue - 100)), вы получите истину ...

но это то, что должно быть:

http://en.wikipedia.org/wiki/Floating_point#Accuracy_problems

думая об этом, у вас есть 64-битное число, представляющее число больше 2 ^ 64 (double.maxvalue), поэтому ожидается неточность.

@ebel

thinking about it, you have 64 bit representing a number greater than 2^64 (double.maxvalue), so inaccuracy is expected.

2 ^ 64 не является максимальным значением двойной точности. 2 ^ 64 - это количество уникальных значений, которые может содержать double (или любой другой 64-битный тип). Double.MaxValue равен 1.79769313486232e308.

Неточность чисел с плавающей запятой возникает не из-за представления значений, превышающих Double.MaxValue (что невозможно, за исключением Double.PositiveInfinity). Это происходит из-за того, что желаемый диапазон значений слишком велик, чтобы поместиться в тип данных. Поэтому мы отказываемся от точности в обмен на большую дальность действия. По сути, мы отбрасываем значащие цифры в обмен на больший диапазон экспоненты.

@DrPizza

Not even; the IEEE encodings use multiple encodings for the same values. Specifically, NaN is represented by an exponent of all-bits-1, and then any non-zero value for the mantissa. As such, there are 252 NaNs for doubles, 223 NaNs for singles.

Истинный. Я не учел повторяющиеся кодировки. Однако на самом деле есть 252-1 NaN для парных игр и 223-1 NaN для одиночных игр. :п

2^64 is not the maximum value of a double. 2^64 is the number of unique values that a double (or any other 64-bit type) can hold. Double.MaxValue is equal to 1.79769313486232e308.

Даже не; кодировки IEEE используют несколько кодировок для одних и тех же значений. В частности, NaN представлено показателем всех битов-1, а затем ненулевым значением любой для мантиссы. Таким образом, есть 252 NaN для парных разрядов, 223 NaN для одиночных игр.

True. I didn't account for duplicate encodings. There are actually 252-1 NaNs for doubles and 223-1 NaNs for singles, though. :p

Дох, забыл вычесть бесконечности.

Грубая версия этой проблемы, которую я узнал, заключается в том, что 32-битные числа с плавающей запятой дают вам точность в 5 разрядов, а 64-битные числа с плавающей запятой дают вам точность в 15 разрядов. Это, конечно, будет варьироваться в зависимости от того, как кодируются числа с плавающей запятой, но это довольно хорошая отправная точка.

Другие вопросы по теме