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





Чтобы узнать больше о подобной глупости, прочтите эту хорошую статью, относящуюся к калькулятору 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 разрядов. Это, конечно, будет варьироваться в зависимости от того, как кодируются числа с плавающей запятой, но это довольно хорошая отправная точка.