Каков наилучший способ сохранить значимые цифры в расчете? - PullRequest
1 голос
/ 02 июля 2010

Допустим, вы хотите преобразовать градусы в радианы:

radians =  degrees * (pi / 180)

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

-32.39    degrees = -0.5653 radians     # 4 significant digits
-32.38795 degrees = -0.5652763 radians  # 7 significant digits

Я был удивлен, что ни на одном языке не нашел примеров того, как выполнить эту, казалось бы, простую операцию.

Моя первая мысль:

degrees_str = degrees
# remove any non-significant leading zeros from degrees_str
# degree_digits = count the remaining digit characters in degrees_str
# radian_int_digits = count the digits in integer portion of the radians
# round radians to (degree_digits - radian_int_digits) digits after the decimal point

Является ли это наиболее эффективным способом выполнения этого общего типа расчета (не относится к градусам / радианам)?

Ответы [ 3 ]

4 голосов
/ 02 июля 2010

Взгляните на интервальную арифметику .

Часто при применении в вычислениях предполагается, что все операции вызывают расширение интервала на одну единицу в последнем месте, поэтому это дает пессимистический результат.

Интервалы могут быть установлены на основе известной точности входов - если у вас есть pi = 3,142, то вы бы сделали константу pi интервалом [3.1415, 3.1425].

Интервалы могут быть установлены на основе известной точности входов - если у вас есть pi = 3,142, то вы бы сделали константу pi интервалом

Предполагая, что 8 сиг-фиг работают для интервалов -вам нужно больше точности в интервале, чем в значениях,

pi = [3.1415000, 3.1425000].  // pi to 4sf

angle = [-32.385000, -32.395000]. // angle to 4sf

degs_to_rads = pi / 180 // exact constant 180
  = [0.017452776, 0.017458334]. // truncated and widened from [0.0174527778,0.0174583333]

rads = pi * angle / 180 
   = [-0.56556274,-0.56520814] // truncated and widened from [-0.56556273,-0.565208151]

width(rads) = abs(-0.56556274 - (-0.56520814)) = -0.0003546

, поэтому, если вы хотите отформатировать rads для целого числа Sig Fig, вы выбрали значащие цифры, чтобы ошибка на интервалене виден;в этом случае

sf  min             max
8   -0.56556274     -0.56520814
5   -0.56556        -0.56521 
4   -0.5656         -0.5652
3   -0.566          -0.565
2   -0.57           -0.57

Таким образом, хотя интервал достаточно мал для входных данных, известных четырем значащим цифрам, результат точен только до двух.

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

3 голосов
/ 02 июля 2010

Арифметика с плавающей точкой сложна, как отмечал ответ Марка Рэнсома.Если вы программируете научный или математический код, убедитесь, что вы полностью понимаете арифметику с плавающей запятой.Убедитесь, что вы полностью понимаете формат IEEE, включая денормализованные числа и, кроме того, общие источники потери точности.Например, ошибка отмены и когда / где числа IEEE округлены ... и концепция машинного эпсилона.Был целый курс по этому вопросу в моем университете ... и я уверен, что эта область намного глубже этого.

По сути, число IEEE Double Precision хранит 53-битный код в мантиссе, котораявроде как 15,9-значная точность ... но не совсем, потому что мантисса находится в основании-2, а "15,9 значащих цифр" подразумевает основание 10. (log (2 ^ 53) составляет ~ 15,9) В целом, концепция значимыхцифры просто бесполезны при использовании чисел с плавающей точкой IEEE.Лучше иметь полное понимание арифметики с плавающей запятой, если вы хотите сохранить точность.

Если вам ДЕЙСТВИТЕЛЬНО нужно вводить значащие цифры, сделайте себе одолжение и избегайте чисел с двойной точностью.Храните их как целые числа.Возможно, у вас есть шанс с числами IEEE Base-10, но их упоминает только C ++ 0x (и я пока не знаю других языков программирования, которые поддерживают числа десятичных64)

2 голосов
/ 02 июля 2010

Понятие значащих цифр не имеет большого значения в вычислениях, потому что компьютер не работает в десятичных цифрах. Возможно, значение -32,39 хранится внутри таким образом, что оно ближе к -32,38999999999999, чем к -32,39000000000000.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...