Ассоциативный, но в пределах погрешности. А если погрешность опережает значащую часть, то, конечно, извините! А если настаивать на том, что значащие разряды там все до последнего бита (например, для побитового сравнения) - то два раза извините.
Собственно, коммутативность и ассоциативность сложения используется в борьбе против ошибок, особенно - ошибок нормализации и денормализации. Потому что мы-то знаем, что от перестановки _искомая_ сумма не меняется.
Смотря что называть "погрешностью". E.g. abs (a0 + a1 + ... + an+x) - (x + a0 + a1 + ... + an) для x=2^24 и 0 < ai < 1 может быть 2^24-1, что явно больше погрешности представления любого слагаемого. Для практических применений он совершенно не ассоциативный.
Для практических применений (физматмоделирование, бухгалтерия) всегда считают погрешность вычислений.
Если у нас одно из слагаемых имеет порядок 1e24, это значит, что ошибка денормализации может достигать 1e0 для каждого сложения, итого может набежать n+2.
Тогда, как честные люди, мы напишем abs((a0+...+an+x)-(x+a0+...+an)) <= eps - что является типичной формулой приближённого сравнения вещественных чисел. Наши суммы приближённо равны, ЧТД (ИЧСХ). Ну да, eps тут здоровенный. Однако, abs(eps/x) <= FLT_EPSILON*(n+2), что не так уж и плохо, э?
Вот нифига. Для подмножества-с-операциями (что это? абелева группа, если речь идёт только о +, или будем дотягивать до алгебры?) представимых float'ов ассоциативность выполняется безо всяких оговорок на погрешность.
0.1 само по себе непредставимо 1e25 + 1 - результат непредставим
А для 1+2+3 всё прекрасно. А если мы вместо дебильного побитового сравнения == будем использовать сравнение с вычисленной погрешностью (а все умные математики и бухгалтеры именно это и делают), то операбельное подмножество флотов окажется гораздо шире.
Это не + неассоциативен, а == некорректно. Вот в чём дело.
А с делением такое в принципе не прокатит. Поэтому давайте не разводите демагогию.
Это и есть: опрометчиво считать все разряды значащими (что делает операция ==).
Даже если бы здесь не было ошибки денормализации (а она есть, поскольку 0.1=0.xxx*2^-4, 0.2=0.xxx*2^-3, 0.3=0.yyy*2^-2), - всё равно, непредставимые двоичные дроби, там самый младший разряд мантиссы содержит ошибку округления. А после двух сложений - ошибку округления содержат уже 2, если не 3 младших разряда.
Можно относиться к этому, как к шуму. Без шумоподавления 0.6±eps != 0.6±eps, даже если мы просто два раза напишем 0.6 и пропустим через шумящий канал.
Просто для фиксированной (или денормализованной) арифметики ошибка набегает линейно, по количеству членов суммы. А для плавающей денормализация может выстрелить сразу на все деньги. (-1e100 + 1e100) + 100500 = 0+100500 = 100500 (-1e100) + (1e100 + 100500) = -1e100 + 1e100 = 0 Но, в масштабах 1e45 (это младший разряд числа 1e100), оба результата практически равны!
Собственно, коммутативность и ассоциативность сложения используется в борьбе против ошибок, особенно - ошибок нормализации и денормализации.
Потому что мы-то знаем, что от перестановки _искомая_ сумма не меняется.
Reply
abs (a0 + a1 + ... + an+x) - (x + a0 + a1 + ... + an) для x=2^24 и 0 < ai < 1 может быть 2^24-1, что явно больше погрешности представления любого слагаемого. Для практических применений он совершенно не ассоциативный.
Reply
Если у нас одно из слагаемых имеет порядок 1e24, это значит, что ошибка денормализации может достигать 1e0 для каждого сложения, итого может набежать n+2.
Тогда, как честные люди, мы напишем abs((a0+...+an+x)-(x+a0+...+an)) <= eps - что является типичной формулой приближённого сравнения вещественных чисел. Наши суммы приближённо равны, ЧТД (ИЧСХ).
Ну да, eps тут здоровенный. Однако, abs(eps/x) <= FLT_EPSILON*(n+2), что не так уж и плохо, э?
Reply
Reply
Reply
Reply
Для подмножества-с-операциями (что это? абелева группа, если речь идёт только о +, или будем дотягивать до алгебры?) представимых float'ов ассоциативность выполняется безо всяких оговорок на погрешность.
0.1 само по себе непредставимо
1e25 + 1 - результат непредставим
А для 1+2+3 всё прекрасно.
А если мы вместо дебильного побитового сравнения == будем использовать сравнение с вычисленной погрешностью (а все умные математики и бухгалтеры именно это и делают), то операбельное подмножество флотов окажется гораздо шире.
Это не + неассоциативен, а == некорректно. Вот в чём дело.
А с делением такое в принципе не прокатит. Поэтому давайте не разводите демагогию.
Reply
In [1]: (0.1+0.2)+0.3==0.1+(0.2+0.3)
Out[1]: False
Ну и на больших суммах конечно разъезжается еще дальше.
Reply
Даже если бы здесь не было ошибки денормализации (а она есть, поскольку 0.1=0.xxx*2^-4, 0.2=0.xxx*2^-3, 0.3=0.yyy*2^-2), - всё равно, непредставимые двоичные дроби, там самый младший разряд мантиссы содержит ошибку округления. А после двух сложений - ошибку округления содержат уже 2, если не 3 младших разряда.
Можно относиться к этому, как к шуму.
Без шумоподавления 0.6±eps != 0.6±eps, даже если мы просто два раза напишем 0.6 и пропустим через шумящий канал.
Просто для фиксированной (или денормализованной) арифметики ошибка набегает линейно, по количеству членов суммы. А для плавающей денормализация может выстрелить сразу на все деньги.
(-1e100 + 1e100) + 100500 = 0+100500 = 100500
(-1e100) + (1e100 + 100500) = -1e100 + 1e100 = 0
Но, в масштабах 1e45 (это младший разряд числа 1e100), оба результата практически равны!
Reply
Leave a comment