Почему порядок влияет на округление при добавлении, что несколько удваиваются в C#

Доступ немного противоречив в том, как отменить событие.

Чтобы отменить подобные сообщения об ошибках, используйте DoCmd.CancelEvent.

Private Sub Form_Error(DataErr As Integer, Response As Integer)
   If DataErr = 3162 then
      MsgBox"ABC"
      DoCmd.CancelEvent
   End if
End sub
7
задан d4nt 30 March 2009 в 12:44
поделиться

7 ответов

Я ожидал бы, что e1+e2 будет равняться e3+e4.

Это не совсем непохоже на ожидание

 floor( 5/3 ) + floor( 2/3 + 1 )

равняться

 floor( 5/3 + 2/3 ) + floor( 1 )

кроме Вы умножаетесь 2^53 перед получением слова.

Используя плавающую точку точности на 12 битов и усечение с Вашими значениями:

1.0            =  1.00000000000
1.1            =  1.00011001100
1.2            =  1.00110011001

1.0 + 1.1      = 10.00011001100 // extended during sum
r1 = 1.0 + 1.1 = 10.0001100110  // truncated to 12 bit
r1  + 1.2      = 11.01001100101 // extended during sum
r2 = r1  + 1.2 = 11.0100110010  // truncated to 12 bit

1.1 + 1.2      = 10.01001100110 // extended during sum
r3 = 1.1 + 1.2 = 10.0100110011  // truncated to 12 bit
r3 + 1.0       = 11.01001100110 // extended during sum
r4 = r3  + 1.0 = 11.0100110011  // truncated to 12 bit

Так изменение порядка операций/усечений вызывает ошибку измениться, и r4! = r2. Если Вы добавляете 1.1 и 1.2 в этой системе, последний бит несет, таким образом, в не потерянный на усечении. Если Вы добавляете 1.0 к 1,1, последний бит 1,1 потерян и таким образом, результатом не является то же.

В одном упорядочивании округление (усечением) удаляет запаздывание 1.

В другом упорядочивании округление удаляет запаздывание 0 оба раза.

Каждый не равняется нулю; таким образом, ошибки не являются тем же.

Удваивается имеют намного больше битов точности, и C#, вероятно, использует округление, а не усечение, но надо надеяться эта простая модель показывает Вам, различные ошибки могут произойти с различными упорядочиваниями тех же значений.

Различие между fp и математикой - то, что + сокращение от того, 'добавьте затем вокруг' вместо того, чтобы просто добавить.

10
ответ дан 6 December 2019 в 07:28
поделиться

c# компилятор ничего не делает. ЦП.

если Вы имеете в регистре ЦП, и Вы затем добавляете B, результатом, сохраненным в том регистре, является A+B, приближенный к плавающей используемой точности

Если Вы затем добавляете C, ошибка складывает. Это ошибочное дополнение не является переходной операцией, таким образом заключительное различие.

6
ответ дан 6 December 2019 в 07:28
поделиться

Посмотрите классическую бумагу (Что каждый программист должен знать об арифметике с плавающей точкой) на предмете. Этот вид материала - то, что происходит с арифметикой с плавающей точкой. Это берет программиста, чтобы сказать Вам, что 1/3+1/3+1/3 is'nt равняются 1...

4
ответ дан 6 December 2019 в 07:28
поделиться

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

double epsilon = 0.0000001;
if (abs(result1 - result2) <= epsilon)
{
    ...
}

Это может представлять интерес: Что Каждый Программист Должен Знать Об Арифметике С плавающей точкой

2
ответ дан 6 December 2019 в 07:28
поделиться

result1 должен всегда равняться result2 праву?

Неправильно. Это правда в математике, но не в арифметике с плавающей точкой.

Необходимо будет прочитать некоторую Числовую Аналитическую краткую информацию.

1
ответ дан 6 December 2019 в 07:28
поделиться

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

Скажем, это для чисел ниже 10, это может сохранить все числа, таким образом, это может сохранить 1, 2, 3, и так далее до и включая 10, но после 10, это может только сохранить каждое второе число, из-за внутренней потери точности, другими словами, это может только сохранить 10, 12, 14, и т.д.

Теперь, с тем примером, Вы будете видеть, почему следующее приводит к различным результатам:

1 + 1 + 1 + 10 = 12 (or 14, depending on rounding)
10 + 1 + 1 + 1 = 10

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

Например, 3.00000000003 + 3.00000000003 мог бы закончить тем, что был 6.00000000005 (заметьте не 6 в конце), но 3.00000000003 + 2.99999999997 мог бы закончить тем, что был 6.00000000001, и с этим:

step 1: 3.00000000003 + 3.00000000003 = 6.00000000005
step 2: 6.00000000005 + 2.99999999997 = 9.00000000002

но, измените порядок:

step 1: 3.00000000003 + 2.99999999997 = 6.00000000001
step 2: 6.00000000001 + 3.00000000003 = 9.00000000004

Таким образом, это будет иметь значение.

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

1
ответ дан 6 December 2019 в 07:28
поделиться

Вы на самом деле не используете те же значения, потому что промежуточные результаты отличаются:

double result1 = 2.1 + 1.2;
double result2 = 2.2 + 1.1;

Поскольку удваивается, не может представить десятичные значения точно, Вы получаете различные результаты.

0
ответ дан 6 December 2019 в 07:28
поделиться
Другие вопросы по тегам:

Похожие вопросы: