Существует ли алгоритм округления, который отменяет преобразование базы 2 и выводит точность? * надеюсь в Java * - PullRequest
1 голос
/ 19 января 2012

Если у меня есть число, например 3.01, компьютер, кажется, считает, что лучшим двойным является 64-битное число:

3.0099999999999997868371792719699442386627197265625

Есть ли какой-нибудь способ лучше, чем искать, скажем, более четырех 9 или 0, которые яможет в общем случае "округлить" до точного базового представления 10?

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

Iдумаю, что большинство чисел, с которыми я имею дело, должно быть достаточно маленьким, чтобы у 64-битных не было двусмысленности.

Ответы [ 3 ]

2 голосов
/ 19 января 2012

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

Если вас интересуют десятичные значения, а не только величина, вам следует учитыватьиспользуя BigDecimal вместо double.(Что представляют собой эти значения?)

РЕДАКТИРОВАТЬ: Как отмечалось в других ответах, Java в любом случае даст вам 3,01, когда вы просто используете toString, однако вы пришли к исходному значению.Это указано в Double.toString:

Сколько цифр должно быть напечатано для дробной части m или a?Должна быть хотя бы одна цифра для представления дробной части, и помимо этого столько, но только столько, сколько цифр необходимо, чтобы однозначно отличить значение аргумента от смежных значений типа double.То есть предположим, что x - это точное математическое значение, представленное десятичным представлением, полученным этим методом для конечного ненулевого аргумента d.Тогда d должно быть двойным значением, ближайшим к x;или если два двойных значения одинаково близки к x, то d должно быть одним из них, а младший значащий бит значения и d должен быть 0.

Если этого достаточно для вас, это 'облегчит жизнь ... но, похоже, вы должны думать об этом более фундаментально.

1 голос
/ 19 января 2012

Понятно, что вы не можете рассчитывать на то, что всегда вернете исходное число, так как есть много чисел, которые отображаются на одно и то же число. Например, вы не можете различить эти числа:

3.0099999999999997868371792719699442386627197265625
3.009999999999999786837179271969944238662
3.009999999999999786837179271
3.0099999999999997
3.01

Однако у Python есть интересный подход: если вы дадите ему номер 3.0099999999999997868371792719699442386627197265625, он ответит 3.01:

Python 2.7.2+ (default, Nov 30 2011, 19:22:03) 
[GCC 4.6.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> 3.0099999999999997868371792719699442386627197265625
3.01

Это потому, что 3.01 - самая короткая строка, которая дает то же число с плавающей запятой. Другими словами, это самый короткий x, так что

float(repr(x)) == x

где repr - это функция Python, которая превращает объект в строку (здесь он превращает 3.0099... в 3.01), а float преобразует строку в число с плавающей точкой.

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

Эта функция была добавлена ​​в Python 2.7 , в качестве бэкпорта для функции Python 3.1. Он был обсужден в Issue1580 , и вы сможете найти там код и перевести его на Java, если хотите.

1 голос
/ 19 января 2012

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

...