Выведите числа 0, 0.1, 0.2, 0.3, …, 3, используя while/do while

Я хочу напечатать числа в диапазоне от 0 до 3 следующим образом:

0, 0.1, 0.2, 0.3, …, 3

но когда я использую этот код:

    double i = 0;
    while (i <= 3) {
        System.out.printf("%.1f, ", i);
        i+= 0.1;
    }

или это:

    double j = 0;
    do {
        System.out.printf("%.1f, ", j);
        j+= 0.1;
    } while (j <= 3);

я получил

0, 0.1, 0.2, 0.3, …, 2.9

Что я делаю неправильно?

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

Joe C 25.01.2019 23:15

Я изменил double на float, и теперь все работает нормально. Спасибо.

BEN1EK 25.01.2019 23:21

@JoeC Отладчик может показать не что иное, как простой System.out.println(i). Это не объясняет, почему в какой-то момент результатом будет 3.0000000000000013, и как можно решить эту проблему.

Marco13 25.01.2019 23:23

@ BEN1EK Даже если вам это не нужно для решения этой проблемы, совет Джо сделает вас лучшим программистом, и точка. Каждый хороший программист знает, как правильно отлаживать код, и инструменты, используемые для отладки, являются одними из самых важных в наборе инструментов разработчика.

corsiKa 25.01.2019 23:23

@corsiKa «Каждый хороший программист знает, как правильно отлаживать код» - и каждый программист отличный знает нет 8-D. Серьезно, вопрос может нуждаться в подсказке к другому (начинающему уровню) Q/A о неточностях с плавающей запятой...

Marco13 25.01.2019 23:25

Конечно, я прочитал статью Джо, и она очень полезна.

BEN1EK 25.01.2019 23:26

@ Marco13, конечно, я могу с этим согласиться. Бен смог это исправить, заменив double на float, но готов поспорить, что он не понимает почему. (Подсказка: Бен: числа с плавающей запятой и двойные числа не могут точно хранить числа, такие как 0.1. Однако они могут очень хорошо выполнять .5, .25, .125, .0625... и т. д. Надеюсь, это укажет вам на правильные причины, почему это происходит.

corsiKa 25.01.2019 23:28

@corsiKa Спасибо. Я изменил свой код на: int i = 0; while (i <= 30) { System.out.printf("%.1f, ", i * 0.1); i++; }

BEN1EK 25.01.2019 23:34
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
2
8
71
1

Ответы 1

Это из-за точности double. Другим решением может быть использование достаточно точного типа данных, например BigDecimal.

BigDecimal i = BigDecimal.ZERO;
while (i.compareTo(BigDecimal.valueOf(3)) <= 0) {
    System.out.printf("%.1f, ", i.doubleValue());
    i = i.add(BigDecimal.valueOf(0.1));
}

Другие вопросы по теме