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

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

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

4 ответов


@PeterLawrey заявляет максимальную точность в 15.

это на самом деле не то, что он указал на всех. Он заявил следующее:--3-->

double имеет 15 десятичных знаков точности

и он ошибается. У них есть 15 decimal цифры точности.

количество десятичных цифр в любом числе задается его журналом в базу 10. 15-это значение пола log10(253-1), где 53-это количество битов мантиссы (включая подразумеваемый бит), как описано в Javadoc и IEEE 754, и 253-1 поэтому максимально возможное значение мантиссы. Фактическое значение составляет 15.954589770191003298111788092734 в пределах калькулятора Windows.

он совершенно не прав, описывая это как "десятичные знаки точности". А double имеет 15 знаков после цифры точность если они все до запятой. для числа с дробными частями вы можете получить намного больше 15 цифр в десятичном представлении из-за несоизмеримости десятичных и двоичных дробей.


вы также можете "измерить" его напрямую:

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

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

4.9 E-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 (вам не хватает 5-го десятичного знака). В этом примере с точностью до 4 десятичных знаков epsilon равен 0.0001. Epsilon непосредственно измеряет точность с плавающей запятой. Просто перенесите в двоичный файл.

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


максимальная точность double of-первое значение, большее 0. Согласно Javadoc двойника, это число представлено Double.MIN_VALUE. Вы можете вывести его следующим образом:

BigDecimal doubleMinVal = BigDecimal.valueOf(Double.MIN_VALUE);
System.out.println(doubleMinVal.toPlainString());
System.out.println(doubleMinVal.toString());

посмотреть эта программа IDEOne для примера.