Как определить максимальную точность для двойного

Я пытаюсь определить, какая максимальная точность для double. В комментариях к принятому ответу в этой ссылке Сохранять точность с двойным в Java @PeterLawrey утверждает максимальную точность в 15.

Как вы это определяете?

Ответ 1

@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 десятичных цифр точности, если они все до десятичной точки. Для чисел с дробными частями вы можете получить более десяти цифр в десятичном представлении из-за несоизмеримости десятичных и двоичных дробей.

Ответ 2

Вы также можете "измерить" его непосредственно:

for(double d = 1 ; d > 0 ; d/=2) System.out.println(d);

Идея этого кода состоит в том, чтобы достичь наименьшего числа одним битом. Итак, вы начинаете с 1 (который имеет только 1 бит) и делятся на два (что сдвигает биты вправо в двоичном формате), пока вы не достигнете последнего бит. Последнее число, напечатанное этим циклом:

4.9E-324

Ответ 3

Запустите этот код и посмотрите, где он останавливается

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. Эпсилон непосредственно измеряет точность с плавающей запятой. Просто переносите в двоичный файл.

Изменить. Ваш вопрос задан "Как определить...". Ответ, который вы искали, был скорее объяснением, чем способом определения точности (с ответом, который вы приняли). В любом случае, для других людей, запуск этого кода на машине будет определять точность для "двойного" типа.

Ответ 4

Максимальная точность 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 для примера.