2012-03-01 2 views
1

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

т.е. 5000034/5000000 = 1,0000068

+0

Включить один из операндов в 'double', а затем разделить? – Jon

+2

Что такое «улл»? –

+0

ull = unsigned long long – BoBTFish

ответ

5

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

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

Вам следует избегать арифметики с плавающей запятой, потому что они не являются точными [у вас есть конечное число бит для представления бесконечного числа чисел в каждом диапазоне, поэтому некоторые срезы должны произойти ...]. Арифметика с фиксированной точкой [как обычно реализуется в больших десятичных библиотеках] позволяет выделять больше бит «на лету», чтобы представить число с требуемой точностью.
Более подробную информацию по этому вопросу с плавающей точкой можно найти в этом [немного расширенный] статья: What Every Computer Scientist Should Know About Floating-Point Arithmetic

+0

Ссылка хорошая, но «самая точная точность» ничего не значит, а машина 'double' обычно является лучшим выбором для точности. –

+0

@JamesKanze: «Самая точная точность» - это то, что просит ОП, конечно, это ничего не значит, что такое «самая точная точность» для 'e' или' pi'? Я имел в виду, что использование арифметики с фиксированной точкой - в отличие от того, что вы получаете с двойной точностью - вы можете ** контролировать ** точность, которую вы получаете, в отличие от плавающей запятой. – amit

0

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

0

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

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

0

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

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