Почему некорректно работает разность 2-х переменных типа double?

import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        double firstDouble = scanner.nextDouble();
        double secondDouble = scanner.nextDouble();

        if (Math.abs(secondDouble - firstDouble) < 0.000001) {
            System.out.println("числа равны");
        } else {
            System.out.println("числа не равны");
        }
        System.out.println(firstDouble - secondDouble);
    }
}

Имеем такой код. Просто программа проверки равенства двух вещественных чисел через сравнение их разности с 0.000001. И да, я знаю про класс java.math.BigDecimal(), но в данном случае я использую казуальный метод сравнения примитивов, но попробуйте прогнать 0.000007 и 0.000006. Казалось бы, условие не выполняется, и вывод должен быть - "не равны". Но нет. А главное, я для проверки в самом конце прописал вывод самой разности этих чисел. Там так и вовсе дичь какая-то. Уважаемые знатоки, что и почему происходит?


Ответы (1 шт):

Автор решения: Zhenyria

Я запустил такой код:

    public static void main(String[] args) {
        double firstDouble = 0.000006;
        double secondDouble = 0.000007;
        System.out.println(Math.abs(secondDouble - firstDouble));
    }

Казалось бы: мы должны получить 0.000001 и false. Но мы получаем 9.999999999999997E-7. Если я ничего не напутал, то это можно выразить как 0.000000999999999....

Так происходит из-за механизма хранения чисел с плавающей точкой в компьютерах. Всех тонкостей вам не расскажу, да вы можете найти их сами, скажу лишь то, что суть в следующем: в компьютерах все числа выражены в двоичной системе счисления, а не в десятичной, к какой мы привыкли, из-за чего получившееся число 0.000001 не круглое. Короче говоря, число 0.000001 не может быть полностью выражено в двоичной системе счисления, для у этого у double просто нет места, поэтому происходят такие вот ошибки.

Ссылка

→ Ссылка