Объяснение вывода Java-программы - PullRequest
5 голосов
/ 28 июля 2011

Я наткнулся на следующую программу

class Boolean {  
  public static void main(String argv[]) {  
    boolean x;  
    x = 4.4f == 4.4;  
    System.out.println(x);  
  }  
} 

Вывод следующей программы: false

Но если мы напишем программу следующим образом, то

class Boolean {  
    public static void main(String argv[]) {  
      boolean x;  
      x = 4.5f == 4.5;  
      System.out.println(x);  
    }  
}

В этом случае вывод будет true

Может кто-нибудь объяснить мне, почему ??

Ответы [ 7 ]

3 голосов
/ 28 июля 2011

Обычно не следует сравнивать значения с плавающей запятой с оператором ==.Вы должны использовать сравнение «достаточно близко», например, проверять, отличаются ли значения каким-либо небольшим значением:

double epsilon = 0.000001</p> <p>boolean equal = Math.abs(value1-value2) < epsilon

В вашем примере 4.4f не равен 4.4, потому что java по умолчанию использует плавающую точкузначения для double type, который является 64-битным, и для их сравнения java преобразует значение 4.4f в double, что приводит к тому, что оно немного отличается от исходного двойного значения 4.4 (из-за проблем, представляющих десятичные дроби в двоичном виде). ​​

Вот хорошая ссылка на числа с плавающей запятой.

1 голос
/ 28 июля 2011

Запустите этот код, чтобы увидеть, как приведение типа float к double работает в этих случаях

    NumberFormat nf = new DecimalFormat("0.00000000000000000000");

    System.out.println(nf.format(4.4f));
    System.out.println(nf.format(4.4));

    System.out.println(nf.format(4.5f));
    System.out.println(nf.format(4.5));
1 голос
/ 28 июля 2011

Проблема в том, что компьютеры любят числа, основанные на базе 2, а не на базе 10, как мы.

4.4 - это бесконечная дробь (например, 0,333333333 ... для нас) в двоичном формате, и числа с плавающей запятой имеют меньше цифр, чем двойные, поэтому в 4.4f меньше цифр, чем в 4.4, что делает их разными.

4.5 не является бесконечной дробью.

Примечание: всякий раз, когда вам нужно сравнить числа с плавающей точкой или двойные, вы всегда должны проверять размер разницы, а не просто проверять равенство.

0 голосов
/ 28 июля 2011

В дополнение к тому, что все сказали, вот очень популярный пример, демонстрирующий эту вещь с помощью операций с плавающей запятой.

System.out.println(0.3 - 0.2 - 0.1);

Не печатается 0. Фактически, он напечатал бы очень маленькое число в результате ошибок усечения, которые происходят в операциях с плавающей запятой, когда определенные дробные части не заканчиваются повторением в двоичном представлении.

0 голосов
/ 28 июля 2011

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

  public static void main(String args[]) {
  double a, b;

  a = 4.4f;
  b = 4.5f;
  System.out.println("4.4f implicitly cast to a double = "+a);
  System.out.println("4.5f implicitly cast to a double = "+b);

  }

Вы увидите, что 4.4f при неявном приведении к удвоению фактически составляет 4.400000095367432.

0 голосов
/ 28 июля 2011

Ваш prgramm сравнивает 16-разрядное число с плавающей запятой с 32-разрядным двойным значением.Внутренне это представляется как IEEE754 , поэтому различие представляет собой ошибку округления, которая в некоторых случаях приводит к этому неравенству из-за различной точности.

0 голосов
/ 28 июля 2011

Это из-за ошибки округления, когда двойник усекается до числа с плавающей точкой. Иногда ты получаешь это, иногда нет.

4.4f - это число с плавающей запятой, а 4.4 - двойное число.

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