Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Java: Общие вопросы > Два раззных результата при одних и тех же действия


Автор: Vitaly333 26.2.2009, 17:07
Код

int n = 100;
     double[] a,b;
     int i;
     a = new double[n]; // Vector a
     b = new double[n]; // Vector b
     
     double res,res1,res2;
     res  = 0.0;
     res1 = 0.0;
     res2 = 0.0;
     
     Random r = new Random();
     for (i = 0;i<n;i++){
        a[i] = r.nextDouble();
        b[i] = r.nextDouble();                  
     }
          
     for (i = 0;i<n;i++) res+=a[i]*b[i];     
     System.out.println("Result = " + res);
     
     
     res = 0.0;
     for (i = 0;i<n/2;i++) res1+=a[i]*b[i];
     for (i = n/2;i<n;i++) res2+=a[i]*b[i];
     res = res1+res2;
     System.out.println("Result = " + res);


Тут просходит скалярное умножение двух векторов. В 1-ом случае вектора перемножаются целиком с 1 - ого до последнего элемента. Результат записывается в переменную res. Во 2-ом случае умножение разделено на две части. Результаты записываются в res1 и res2 соответственно и потом складываются. В обоих случаях результат получается очень близким друг к другу но всё же отличным в 13 - 15 знаке
Вот пример случайного запуска:

Код

Result = 19.682322519550098
Result = 19.682322519550105

Почему так происходит?

Автор: COVD 26.2.2009, 18:11
Не удивительно - в операциях с вещественными числами (float, double) ошибки округления зависят от порядка выполнения операций.

Автор: Vitaly333 26.2.2009, 21:32
Цитата

Не удивительно - в операциях с вещественными числами (float, double) ошибки округления зависят от порядка выполнения операций. 

Хорошо, тогда в каком  случае резудьтат считается более точным?

Автор: COVD 26.2.2009, 22:25
Ошибка округления при вычислениях имеет обыкновение накапливаться. Алгоритмы анализируют на чувствительность к ошибкам округления. Абсолютно точны только целочисленные вычисления.  Если не ошибаюсь, это предмет науки "Численные методы".

Автор: rygel 27.2.2009, 08:33
Используй BigDecimal

Автор: math64 27.2.2009, 09:11
Второй вариант скорее всего более точный.
Отсортируй массив произведений. Начинай складывать с меньших по модулю.

Автор: gosnis 27.2.2009, 12:38
Цитата(math64 @ 27.2.2009,  09:11)
Второй вариант скорее всего более точный.
Отсортируй массив произведений. Начинай складывать с меньших по модулю.

Что то я немного торможу. Почему второй вариант более точный? Чем они вообще отличаются с математической точки зрения?

Автор: math64 1.3.2009, 14:41
Ну допустим нужно сложить 1 и 1E11 раз 1E-11, сложение с точностью 10 знаков.
Если начинать складывать с 1 получишь результат 1 (1 + 1E-11 = 1).
Если складывать меньшие из оставшихся, получишь правльный результат 2.

Автор: dorogoyIV 1.3.2009, 17:29
Цитата(gosnis @  27.2.2009,  12:38 Найти цитируемый пост)
с математической точки зрения

иногда математика не очень точная наука  smile 
пользуйся принятыми всеми методами (а то ведь можно и иголочки побросать - метод Монте-Карло например)

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)