Потеря точности после передачи параметра - PullRequest
0 голосов
/ 07 февраля 2019

У меня есть длинная, которая имеет большую ценность.Затем я пытаюсь передать его как параметр функции, которая принимает удвоение, после чего точность теряется.Почему это так и как этого избежать?

long bigValue = 3038528443022066688L;
foo(bigValue);
 ...

foo(double value){
 System.out.printlin(value);
}

Фактический результат: 3.0385284430220667E18 Ожидаемое: исходное значение

Я знаю, что не каждая длинная может быть представлена ​​как двойная, но какя могу сохранить первоначальное значение?

Ответы [ 2 ]

0 голосов
/ 07 февраля 2019

Двойной является значением с плавающей точкой.Это подразумевает, что оно никогда не имеет точного значения.Любая плавающая точка имеет некоторую точность, толерантность или ошибку.

Другими словами, плавающая точка всегда является лишь приблизительной.Апроксимация может достичь точного значения, как и любой апроксимарион может , но все еще остается приблизительной.

Это имеет важные последствия: вы не можете просто кормить двойные числа в формулеученый.Попытка так приводит в общем к непригодным ненадежным / неправильным результатамВместо этого вы должны найти формулу замены, которая учитывает, что она является приблизительной.Например, деление и корни стабилизируются, различия значений разных размеров приводят к ошибкам и требуют масштабирования ...

Имея это в виду, вы получите 3.0385284430220667E18 в качестве приблизительного значения 3038528443022066688 - что является допустимым приближением.

Это произошло, когда вы сказали Java создать двойное число (обычное: приблизительное) из вашего длинного (которое было «дискретным» числом, и исчисление должно принимать это во внимание: дискретная математика или как Кнут называет это «конкретным»).

0 голосов
/ 07 февраля 2019

Просто невозможно сохранить упомянутое значение как double в его полной точности.

3038528443022066688 имеет двоичную точность 62 бита.A double, однако, имеет только мантиссу (AFAIR) 53 бит.Итак, 9 бит потеряны.Этого нельзя избежать, если вы работаете с double.

Если вы можете себе это позволить, вы можете остаться с long, в противном случае вы можете использовать BigInteger или BigDecimal, в зависимости от ваших потребностей.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...