Подразделение CPP - как получить наиболее точный результат? - PullRequest
1 голос
/ 01 марта 2012

Я хочу разделить две переменные типа Ull и получить наиболее точный результат.Каков наилучший способ сделать это?

т.е. 5000034/5000000 = 1,0000068

Ответы [ 4 ]

5 голосов
/ 01 марта 2012

Если вам нужна «самая точная точность» - вам следует избегать арифметики с плавающей запятой.

Возможно, вы захотите использовать некоторую большую десятичную библиотеку [которая обычно реализует фиксированная точка арифметика] и позволит вам определить точность, которую вы ищете.

Вы должны избегать арифметики с плавающей запятой, потому что они не точны [у вас есть конечное число битов для представления бесконечного числа чисел в каждом диапазоне, поэтому должно происходить некоторое срезание ...]. Арифметика с фиксированной запятой [как обычно реализуется в больших десятичных библиотеках] позволяет выделять больше битов «на лету» для представления числа с желаемой точностью.
Более подробную информацию о проблеме с плавающей запятой можно найти в этой [немного продвинутой] статье: Что должен знать каждый компьютерщик об арифметике с плавающей запятой

1 голос
/ 01 марта 2012

Вместо (двойной) (N) / D, сделайте 1 + ((двойной) (N - D) / D)

0 голосов
/ 01 марта 2012

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

0 голосов
/ 01 марта 2012

Боюсь, что «самый точный результат» мало что значит.Ни одно конечное представление не может точно представить все действительные числа;насколько точным может быть представление, зависит от размера типа и его внутреннего представления.В большинстве реализаций double даст точность около 17 десятичных цифр, что, как правило, на несколько порядков точнее, чем ввод;для одного умножения или деления обычно вполне подходит double.(Проблемы возникают с сложением и вычитанием, когда разница между двумя значениями чрезвычайно велика.) Существуют пакеты, которые обеспечивают большую точность (BigDecimal, BigFloat и т. П.), Но они никогда не бывают точными: в конце концов, точностьограничено объемом памяти, который вы готовы позволить им использовать.Они также намного медленнее, чем double, и, как правило, (немного) сложнее в правильном использовании (поскольку у них больше опций, например, какой точности вы хотите).Единственный реальный ответ на ваш вопрос - другой вопрос: сколько точности вам нужно?И для какой последовательности операций?Ошибки округления накапливаются, поэтому, хотя double может быть достаточно для одного деления, оно может вызвать проблемы, если наивно использовать его для итерационных процедур.Хотя в таких случаях решение обычно состоит не в том, чтобы повысить точность, а в том, чтобы изменить алгоритм таким образом, чтобы избежать проблем.Если double дает вам необходимую точность, используйте ее вместо любого расширенного типа.Если это не так, и у вас нет выбора, выберите одну из существующих библиотек произвольной точности, например GMP.

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

...