Почему я вижу двойную переменную, инициализированную к некоторому значению как 21,4 как 21,399999618530273?

В Java все находится в форме класса.

Если вы хотите использовать любой объект, тогда у вас есть две фазы:

  1. Объявить
  2. Инициализация

Пример:

  • Объявление: Object a;
  • Инициализация: a=new Object();

То же самое для концепции массива

  • Объявление: Item i[]=new Item[5];
  • Инициализация: i[0]=new Item();

Если вы не дают секцию инициализации, тогда возникает NullpointerException.

46
задан 8 revs, 5 users 29% 4 January 2014 в 19:11
поделиться

13 ответов

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

Между прочим, печать этих значений во времени выполнения часто все еще приводит к корректным результатам, по крайней мере, с помощью современных компиляторов C++. Для большинства операций это не большая часть проблемы.

57
ответ дан Konrad Rudolph 26 November 2019 в 20:07
поделиться

Мне понравилось объяснение Joel , который занимается подобной двоичной проблемой точности с плавающей точкой в Excel 2007:

Видят, как существует много из 0110 0110 0110 там в конце? Поэтому 0.1 имеет никакое точное представление в двоичном файле ..., это - повторяющееся двоичное число. Это - вид подобных, как 1/3 не имеет никакого представления в десятичном числе. 1/3 0.33333333, и необходимо продолжать писать 3 навсегда. При потере терпения Вы получаете что-то неточное.

, Таким образом, можно вообразить, как, в десятичном числе, если Вы пытались сделать 3*1/3, и у Вас не было времени для записи 3 навсегда, результат, который Вы получите, был бы 0.99999999, не 1, и люди станут рассерженными на Вас для того, чтобы быть неправыми.

38
ответ дан Jeff Atwood 26 November 2019 в 20:07
поделиться

Если у Вас есть значение как:

double theta = 21.4;

И Вы хотите сделать:

if (theta == 21.4)
{
}

необходимо быть немного умными, необходимо будет проверить, ли значение теты действительно близко к 21,4, но не обязательно то значение.

if (fabs(theta - 21.4) <= 1e-6)
{
}
11
ответ дан Michael Yaworski 26 November 2019 в 20:07
поделиться

Это является частично определенным для платформы - и мы не знаем, какую платформу Вы используете.

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

, Учитывая, что отладчик видит "фактическое" значение, это получено для создания личного выбора о том, что отобразиться - это могло показать Вам значение, округленное к нескольким десятичным разрядам или более точному значению. Некоторые отладчики делают лучшее задание, чем другие при том, чтобы читать мысли разработчиков, но это - фундаментальная проблема с двоичными числами с плавающей точкой.

7
ответ дан Jon Skeet 26 November 2019 в 20:07
поделиться

Используйте фиксированную точку decimal тип, если Вы хотите устойчивость в пределах точности. Существуют издержки, и необходимо явно бросить, если Вы хотите преобразовать в плавающую точку. Если Вы действительно преобразуете в плавающую точку, то Вы повторно представите нестабильность, которая, кажется, беспокоит Вас.

Поочередно можно преобладать над ним и учиться работать с ограниченная точность арифметики с плавающей точкой. Например, можно использовать округление, чтобы заставить значения сходиться, или можно использовать сравнения эпсилона для описания допуска. "Эпсилон" является константой, которую Вы настраиваете, который определяет допуск. Например, можно принять решение расценить два значения, как являющиеся равным, если они в 0.0001 друг из друга.

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

<час>

Для ЭПСИЛОНА представлений экспоненты мантиссы должен быть вычислен, чтобы остаться в представимой точности. Для номера N Эпсилон = N / 10E+14

System.Double.Epsilon является самым маленьким представимым положительным значением для эти Double тип. Это также маленькое для нашей цели. Читайте совет Microsoft относительно равенства, тестирующего

5
ответ дан Peter Wone 26 November 2019 в 20:07
поделиться

Я столкнулся с этим прежде ( на моем блоге ) - я думаю, что удивление имеет тенденцию быть, что 'иррациональные' числа отличаются.

'иррациональным' здесь я просто обращаюсь к тому, что они не могут быть точно представлены в этом формате. Реальные иррациональные числа (как ПЂ - пи) не могут быть точно представлены вообще.

Большинство людей знакомо с 1/3, не работающим в десятичном числе: 0.3333333333333...

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

1.1 11 x 10^-1

, Когда на самом деле они находятся в основе 2

1.1, 154811237190861 x 2^-47

, Вы не можете избежать его, просто необходимо привыкнуть к тому, что некоторые плавания 'иррациональны', таким же образом это, 1/3.

4
ответ дан Keith 26 November 2019 в 20:07
поделиться

Одним путем можно избежать, чтобы это пользовалось библиотекой, которая использует альтернативный метод представления десятичных чисел, такой как BCD

3
ответ дан SmacL 26 November 2019 в 20:07
поделиться

Кажется мне, что 21.399999618530273 одинарная точность представление (плавающее) 21,4. Похож на отладчик, бросает по сравнению с дважды для плавания куда-нибудь.

3
ответ дан MikeJ-UK 26 November 2019 в 20:07
поделиться

Если Вы используете Java, и Вы нуждаетесь в точности, используете класс BigDecimal для вычислений с плавающей точкой. Это медленнее, но более безопасно.

2
ответ дан Shimi Bandiel 26 November 2019 в 20:07
поделиться

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

, Но большую часть времени можно просто проигнорировать его. 21.4 == 21.4 все еще было бы верно, потому что это - все еще те же числа с той же ошибкой. Но 21.4f == 21.4 может не быть верным, потому что ошибка для плавания и дважды отличается.

при необходимости в зафиксированной точности, возможно, необходимо попробовать числа фиксированной точки. Или даже целые числа. Я, например, часто использую интервал (1000*x) для передачи для отладки пейджера.

2
ответ дан akalenuk 26 November 2019 в 20:07
поделиться

Если это беспокоит Вас, можно настроить способ, которым некоторые значения отображены во время отладки. Используйте его с осторожностью:-)

Отладка Улучшения с Атрибутами дисплея Отладчика

1
ответ дан Larry 26 November 2019 в 20:07
поделиться

Обратитесь к , Общая Десятичная система исчисления

Также обращает внимание при сравнении плаваний, видит этот ответ для получения дополнительной информации.

0
ответ дан 2 revs 26 November 2019 в 20:07
поделиться
Другие вопросы по тегам:

Похожие вопросы: