Я знаю, что у арифметики с плавающей точкой есть проблемы точности. Я обычно преодолеваю их, переключаясь на фиксированное десятичное представление числа или просто игнорируя ошибку.
Однако я не знаю, каковы причины этой неточности. Почему существует так много проблем округления с числами с плавающей запятой?
decimal
работает тип .NET . Фиксированная точка, с другой стороны, отличается. Пока ваш диапазон ограничен, фиксированная точка является хорошим ответом. Но ограничительный диапазон делает фиксированную точку непригодной для многих математических приложений, и в результате реализации чисел с фиксированной точкой часто не оптимизируются аппаратно.Ответы:
Это потому, что некоторые дроби нуждаются в очень большом (или даже бесконечном) количестве мест, которые можно выразить без округления. Это верно как для десятичной записи, так и для двоичной или любой другой. Если вы захотите ограничить количество десятичных разрядов, которые будут использоваться для ваших расчетов (и не будете делать вычисления в дробной записи), вам придется округлить даже простое выражение до 1/3 + 1/3. Вместо записи 2/3 в результате вы должны будете написать 0,33333 + 0,33333 = 0,66666, что не совпадает с 2/3.
В случае компьютера количество цифр ограничено техническим характером его памяти и регистров процессора. Двоичная нотация, используемая внутри, добавляет некоторые дополнительные трудности. Компьютеры обычно не могут выражать числа в дробной нотации, хотя некоторые языки программирования добавляют эту возможность, что позволяет в определенной степени избежать этих проблем.
Что каждый ученый должен знать об арифметике с плавающей точкой
источник
Прежде всего, ошибки округления происходят из-за того, что бесконечность всех действительных чисел не может быть представлена конечной памятью компьютера , не говоря уже о крошечном куске памяти, таком как одна переменная с плавающей запятой , поэтому многие сохраненные числа являются лишь приближениями число, которое они должны представлять.
Поскольку существует только ограниченное число значений, которые не являются приближением, и любая операция между приближением и другим числом приводит к приближению, ошибки округления практически неизбежны .
Важно понять, когда они могут вызвать проблемы, и предпринять шаги для снижения рисков .
В дополнение к важной статье Дэвида Голдберга « Что должен знать каждый компьютерщик» об арифметике с плавающей запятой (переизданной Sun / Oracle в качестве приложения к их Руководству по числовым вычислениям ), о которой упоминал Торстен , журнал « Перегрузка» ACCU показал отличную работу. серия статей Ричарда Харриса о блюзе с плавающей точкой .
Серия началась с
Ричард начинает с объяснения таксономии действительных чисел, рациональных, иррациональных, алгебраических и трансцендентных. Затем он продолжает объяснять представление IEEE754, прежде чем перейти к ошибке отмены и порядку проблем выполнения.
Если вы читаете не глубже этого, у вас будет отличное представление о проблемах, связанных с числами с плавающей запятой.
Если вы хотите узнать больше, он продолжает
Затем он переключается на попытки помочь вам вылечить ваш Calculus Blues
и наконец, что не менее важно, есть
Целый ряд статей стоит того, чтобы их изучить, и в общей сложности на 66 страницах они все же меньше, чем 77 страниц статьи Гольдберга .
Хотя эта серия охватывает большую часть той же темы, я нашел ее более доступной, чем статья Голдберга . Я также обнаружил, что легче понять более сложные части статьи после прочтения более ранних статей Ричардса, а после этих ранних статей Ричард разветвляется на многие интересные области, не затронутые в статье Голдберга.
Как говорил Спак в комментариях:
источник
Ну, у Торстена есть окончательная связь . Я бы добавил:
Любая форма представления будет иметь некоторую ошибку округления для некоторого числа. Попробуйте выразить 1/3 в IEEE с плавающей запятой или в десятичной. Никто не может сделать это точно. Это выходит за рамки ответа на ваш вопрос, но я успешно использовал это правило:
источник
Кажется, что до сих пор не было упомянуто о понятиях неустойчивого алгоритма и плохо обусловленной проблемы . Сначала я расскажу о первом, так как это кажется более частой ошибкой для начинающих нумераторов.
Рассмотрим вычисление степеней (взаимного) золотого сечения
φ=0.61803…
; Один из возможных способов - использовать формулу рекурсииφ^n=φ^(n-2)-φ^(n-1)
, начиная сφ^0=1
иφ^1=φ
. Если вы выполните эту рекурсию в своей любимой вычислительной среде и сравните результаты с точно оцененными возможностями, вы обнаружите медленную эрозию значительных цифр. Вот что происходит, например, в Mathematica :Предполагаемый результат для
φ^41
имеет неправильный знак, и даже ранее, вычисленные и фактические значения дляφ^39
общего не имеют общих цифр (3.484899258054952
* ^ - 9for the computed version against the true value
7.071019424062048*^-9
). Алгоритм, таким образом, нестабилен, и не следует использовать эту формулу рекурсии в неточной арифметике. Это связано с природой формулы рекурсии: для этой рекурсии существует «затухающее» и «растущее» решение, и попытка вычислить «затухающее» решение путем прямого решения, когда есть альтернативное «растущее» решение, требует для численного горя. Таким образом, следует убедиться, что его / ее численные алгоритмы стабильны.Теперь о понятии плохо обусловленной проблемы: даже если может существовать устойчивый способ сделать что-то численно, вполне может оказаться, что проблема, с которой вы столкнулись, просто не может быть решена вашим алгоритмом. Это вина самой проблемы, а не метод решения. Каноническим примером в числовом выражении является решение линейных уравнений с использованием так называемой «матрицы Гильберта»:
Матрица является каноническим примером плохо обусловленной матрицы: попытка найти систему с большой матрицей Гильберта может привести к неточному решению.
Вот демонстрация Mathematica : сравните результаты точной арифметики
и неточная арифметика
(Если вы попробовали это в Mathematica , вы заметите несколько сообщений об ошибках, предупреждающих о появлении плохих условий.)
В обоих случаях простое повышение точности не является лекарством; это только задержит неизбежное размывание цифр.
Это то, с чем вы можете столкнуться. Решения могут быть трудными: во-первых, вы либо возвращаетесь к чертежной доске, либо просматриваете журналы / книги / что угодно, чтобы найти, если кто-то еще придумал лучшее решение, чем вы; во-вторых, вы либо сдаетесь, либо переформулируете свою проблему в более подходящую для себя сторону
Я оставлю вам цитату от Дайан О'Лири:
источник
потому что десятичные числа базы 10 не могут быть выражены в базе 2
или, другими словами, 1/10 не может быть преобразовано в дробь со степенью 2 в знаменателе (что в сущности представляют собой числа с плавающей запятой)
источник
9*3.3333333
в десятичном виде и сопоставь это с9*3 1/3
.1 + .1 != .2
потому что используется двоичное кодирование с плавающей точкой, а не десятичное.1.0/3.0*3.0 != 1.0
поскольку используется двоичное кодирование с плавающей точкой, а не триное.В математике существует бесконечно много рациональных чисел. 32-разрядная переменная может иметь только 2 32 различных значения, а 64-разрядная переменная - только 2 64 значения. Следовательно, существует бесконечно много рациональных чисел, которые не имеют точного представления.
Мы могли бы придумать схемы, которые позволили бы нам идеально представлять 1/3 или 1/100. Оказывается, что для многих практических целей это не очень полезно. Есть одно большое исключение: в финансах часто появляются десятичные дроби. Это в основном потому, что финансы - это, по сути, человеческая деятельность, а не физическая.
Поэтому мы обычно выбираем двоичную с плавающей запятой и округляем любое значение, которое не может быть представлено в двоичном виде. Но в финансах мы иногда выбираем десятичную с плавающей запятой и округляем значения до ближайшего десятичного значения.
источник
"√2"
. (Мой старый калькулятор HP-48 был в состоянии сделать именно это, и квадрат этого значения привел точно2.0
.) Существует только счетная бесконечность представимых действительных чисел для любого конечного представления - но никакие вычисления не могут дать число, которое не в принципе представительный. На практике двоичные числа с плавающей запятой резко ограничивают набор представимых чисел, обеспечивая невероятную скорость и крошечное хранение по сравнению с символическими представлениями.единственная действительно очевидная "проблема округления" с числами с плавающей точкой, о которой я думаю, это с фильтрами скользящих средних
$$ \ begin {align} y [n] & = \ frac {1} {N} \ sum \ limit_ {i = 0} ^ {N-1} x [ni] \ & = y [n-1] + \ frac {1} {N} (x [n] - x [nN]) \ \ end {align} $$
чтобы сделать эту работу без накопления шума, вы должны убедиться, что $ x [n] $, который вы добавляете в текущие выборки, точно такой же, как $ x [nN] $, из которого вы вычтете $ N $ выборок в будущее. если это не так, то отличается то, что маленькая какашка застревает в линии задержки и никогда не выйдет. это потому, что этот фильтр скользящего среднего на самом деле построен с IIR, который имеет минимально устойчивый полюс в $ z = 1 $ и ноль, который отменяет его внутри. но это интегратор, и любое дерьмо, которое интегрируется и не удаляется полностью, будет существовать в сумме интегратора навсегда. Здесь фиксированная точка не имеет той же проблемы, что и числа с плавающей точкой.
источник