Я пытаюсь определить, какая максимальная точность для double. В комментариях к принятому ответу в этой ссылке Сохранять точность с двойным в Java @PeterLawrey утверждает максимальную точность в 15.
Как вы это определяете?
Я пытаюсь определить, какая максимальная точность для double. В комментариях к принятому ответу в этой ссылке Сохранять точность с двойным в Java @PeterLawrey утверждает максимальную точность в 15.
Как вы это определяете?
@PeterLawrey утверждает максимальную точность в 15.
На самом деле это не то, что он заявил вообще. Он заявил:
double имеет 15 десятичных знаков точности
и он ошибается. Они имеют 15 десятичных цифр точности.
Число десятичных цифр в любом числе задается его журналом на основании 10. 15 - это значение пола log 10 (2 53 -1), где 53 - количество бит мантиссы (включая подразумеваемый бит), как описано в Javadoc и IEEE 754, и 2 53 -1, следовательно, является максимально возможным значением мантиссы. Фактическое значение составляет 15.954589770191003298111788092734 до пределов калькулятора Windows.
Он ошибочно описывает его как "десятичные точки точности". A double
имеет 15 десятичных цифр точности, если они все до десятичной точки. Для чисел с дробными частями вы можете получить более десяти цифр в десятичном представлении из-за несоизмеримости десятичных и двоичных дробей.
Вы также можете "измерить" его непосредственно:
for(double d = 1 ; d > 0 ; d/=2) System.out.println(d);
Идея этого кода состоит в том, чтобы достичь наименьшего числа одним битом. Итак, вы начинаете с 1
(который имеет только 1 бит) и делятся на два (что сдвигает биты вправо в двоичном формате), пока вы не достигнете последнего бит. Последнее число, напечатанное этим циклом:
4.9E-324
Запустите этот код и посмотрите, где он останавливается
public class FindPrecisionDouble {
static public void main(String[] args) {
double x = 1.0;
double y = 0.5;
double epsilon = 0;
int nb_iter = 0;
while ((nb_iter < 1000) && (x != y)) {
System.out.println(x-y);
epsilon = Math.abs(x-y);
y = ( x + y ) * 0.5;
}
final double prec_decimal = - Math.log(epsilon) / Math.log(10.0);
final double prec_binary = - Math.log(epsilon) / Math.log(2.0);
System.out.print("On this machine, for the 'double' type, ");
System.out.print("epsilon = " );
System.out.println( epsilon );
System.out.print("The decimal precision is " );
System.out.print( prec_decimal );
System.out.println(" digits" );
System.out.print("The binary precision is " );
System.out.print( prec_binary );
System.out.println(" bits" );
}
}
Переменная y
становится наименьшим значением, отличным от 1.0
. На моем компьютере (Mac Intel Core i5) он останавливается на 1.1102...E-16
. Затем он печатает точность (в десятичной и двоичной).
Как указано в https://en.wikipedia.org/wiki/Machine_epsilon, точность с плавающей запятой можно оценить с помощью значения epsilon. Это "наименьшее число, которое при добавлении к одному дает результат, отличный от одного" (я сделал небольшое изменение: 1-e вместо 1 + e, но логика одна и та же)
Я объясню в десятичной форме: если у вас есть точность в 4 десятичных знака, вы можете выразить 1.0000 - 0.0001, но вы не можете выразить число 1.00000-0.00001 (вам не хватает пятого десятичного разряда). В этом примере с точностью до 4 дециметров эпсилон равен 0,0001. Эпсилон непосредственно измеряет точность с плавающей запятой. Просто переносите в двоичный файл.
Изменить. Ваш вопрос задан "Как определить...". Ответ, который вы искали, был скорее объяснением, чем способом определения точности (с ответом, который вы приняли). В любом случае, для других людей, запуск этого кода на машине будет определять точность для "двойного" типа.
Максимальная точность double
of - это первое значение, большее 0. Согласно Double Javadoc, это число представлено Double.MIN_VALUE
, Вы можете вывести его следующим образом:
BigDecimal doubleMinVal = BigDecimal.valueOf(Double.MIN_VALUE);
System.out.println(doubleMinVal.toPlainString());
System.out.println(doubleMinVal.toString());
См. эту программу IDEOne для примера.