0Pricing
Java Academy · Урок

Почему не стоит использовать double для денег

Проблемы точности чисел с плавающей запятой

«Почему не стоит использовать double для денег» — бесплатный урок Java Academy на CoddyKit. Это урок 1 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения Java Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс Java Academy содержит 4 уроков всего.

Опасное значение по умолчанию

Кажется естественным хранить цены в типе double. К сожалению, double не может точно представить большинство десятичных дробей, из-за чего возникают небольшие ошибки, способные испортить финансовые расчёты.

Классическая неожиданность

Если сложить 0.1 и 0.2 с помощью double, результатом не будет 0.3. Вы получите значение с небольшой ошибкой округления.

public class Main {
    public static void main(String[] args) {
        double result = 0.1 + 0.2;
        System.out.println(result);
    }
}

Почему это происходит

Компьютеры хранят значения double в двоичной системе. Подобно тому как одну треть нельзя точно записать в десятичной системе, многие десятичные дроби, например 0.1, нельзя точно записать в двоичной системе.

В памяти сохраняется ближайшее двоичное приближение, и ошибка накапливается.

Ошибки накапливаются

Одна небольшая ошибка может показаться безобидной, но в цикле по тысячам операций разница накапливается и превращается в заметные неточности.

public class Main {
    public static void main(String[] args) {
        double total = 0.0;
        for (int i = 0; i < 10; i++) {
            total += 0.1;
        }
        System.out.println(total);
    }
}

Сравнение на равенство даёт сбой

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

public class Main {
    public static void main(String[] args) {
        double a = 0.1 + 0.2;
        double b = 0.3;
        System.out.println(a == b);
    }
}

Деньгам нужна точность

В финансовых расчётах ошибка даже в долю копейки недопустима. Аудиторы ожидают, что итоговые суммы будут совпадать до последней копейки.

Поэтому деньги никогда не следует хранить в типе с плавающей запятой.

Решение: BigDecimal

Java предоставляет BigDecimal — класс, который хранит десятичные числа точно. Он отдельно отслеживает немасштабированное значение и параметр scale, поэтому 0.1 действительно означает 0.1.

import java.math.BigDecimal;

public class Main {
    public static void main(String[] args) {
        BigDecimal a = new BigDecimal("0.1");
        BigDecimal b = new BigDecimal("0.2");
        System.out.println(a.add(b));
    }
}

Всегда используйте конструктор со строкой

Создавайте BigDecimal из строки, а не из значения double. Передача значения double переносит двоичную ошибку в BigDecimal.

import java.math.BigDecimal;

public class Main {
    public static void main(String[] args) {
        BigDecimal fromDouble = new BigDecimal(0.1);
        BigDecimal fromString = new BigDecimal("0.1");
        System.out.println(fromDouble);
        System.out.println(fromString);
    }
}

Или используйте valueOf

BigDecimal.valueOf — это безопасное сокращение. Оно преобразует double через его каноническое строковое представление и устраняет исходную двоичную ошибку.

import java.math.BigDecimal;

public class Main {
    public static void main(String[] args) {
        BigDecimal price = BigDecimal.valueOf(19.99);
        System.out.println(price);
    }
}

Хранение денег в копейках

Для простых случаев можно хранить деньги как целое количество копеек, используя long. Тогда 19.99 доллара превращаются в 1999 копеек, а вся математика выполняется точно как целочисленная арифметика.

public class Main {
    public static void main(String[] args) {
        long cents = 1999;
        long total = cents * 3;
        System.out.println(total + " cents");
    }
}

Главный вывод

Используйте float и double в научных и графических задачах, где допустимы небольшие ошибки. Для денег и любых значений, требующих точности, используйте BigDecimal или целое количество копеек.

Быстрая проверка

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

Повторение

Вы узнали, почему числа с плавающей запятой не подходят для денег:

  • Двоичная арифметика с плавающей запятой не может точно хранить многие десятичные дроби
  • Ошибки, например в выражении 0.1 + 0.2, из-за которых результат не равен 0.3, накапливаются
  • Используйте BigDecimal для точной десятичной арифметики
  • Создавайте его из строки или с помощью valueOf, но никогда не передавайте необработанное значение double
  • Хранение целого количества копеек — ещё один точный вариант

Часто задаваемые вопросы

Урок «Почему не стоит использовать double для денег» бесплатный?

Да — полный текст урока «Почему не стоит использовать double для денег» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс Java Academy, подпишись на CoddyKit PRO. Курс Java Academy содержит 4 уроков всего.

Чему я научусь в уроке «Почему не стоит использовать double для денег»?

Проблемы точности чисел с плавающей запятой Ты практикуешь Java Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.

Нужен ли мне опыт, чтобы начать Java Academy?

Предыдущий опыт не требуется. Java Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 1 из 4.

Сколько времени занимает урок «Почему не стоит использовать double для денег»?

Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.

Можно ли писать и запускать код в этом уроке Java Academy?

Да. Каждый урок Java Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.

Все уроки этого курса

  1. Почему не стоит использовать double для денег
  2. Работа с BigDecimal
  3. Округление и масштаб
  4. BigInteger для огромных чисел
← Назад к Java Academy