В моем коде это умножение в коде C ++ со всеми типами переменных как double []
f1[0] = (f1_rot[0] * xu[0]) + (f1_rot[1] * yu[0]);
f1[1] = (f1_rot[0] * xu[1]) + (f1_rot[1] * yu[1]);
f1[2] = (f1_rot[0] * xu[2]) + (f1_rot[1] * yu[2]);
f2[0] = (f2_rot[0] * xu[0]) + (f2_rot[1] * yu[0]);
f2[1] = (f2_rot[0] * xu[1]) + (f2_rot[1] * yu[1]);
f2[2] = (f2_rot[0] * xu[2]) + (f2_rot[1] * yu[2]);
соответствующие этим значениям
Force Rot1 : -5.39155e-07, -3.66312e-07
Force Rot2 : 4.04383e-07, -1.51852e-08
xu: 0.786857, 0.561981, 0.255018
yu: 0.534605, -0.82715, 0.173264
F1: -6.2007e-07, -4.61782e-16, -2.00963e-07
F2: 3.10073e-07, 2.39816e-07, 1.00494e-07
это умножение, в частности, дает неправильное значение -4,61782e-16 вместо 1,04745e-13
f1[1] = (f1_rot[0] * xu[1]) + (f1_rot[1] * yu[1]);
Я вручную проверил другие умножения на калькуляторе, и все они, кажется, дают правильные значения.
это открытый скомпилированный mpi-код, и приведенный выше результат предназначен для запуска одного процессора; при запуске нескольких процессоров разные значения, например, для 40 процессоров получается 1.66967e-13 в результате умножения F1 [1].
Это какая-то ошибка MPI? или проблема точности типа? и почему это работает хорошо для других умножений?
Ваша проблема является очевидным результатом того, что называется катастрофическим суммированием:
Как мы знаем, с плавающей запятой двойной точности можно обрабатывать числа около 16 значащих десятичных знаков.
f1[1] = (f1_rot[0] * xu[1]) + (f1_rot[1] * yu[1])
= -3.0299486605499998e-07 + 3.0299497080000003e-07
= 1.0474500005332475e-13
Это то, что мы получаем с числами, которые вы дали в вашем примере.
Заметить, что (-7) - (-13) = 6
, что соответствует количеству десятичных знаков в плавающей запятой, которое вы даете в своем примере: (например: -5.39155e-07 -3.66312e-07, каждая мантисса имеет точность 6 десятичных знаков). Это означает, что вы использовали здесь поплавки одинарной точности.
Я уверен, что в ваших расчетах точность ваших чисел выше, поэтому вы найдете более точный результат.
В любом случае, если вы используете поплавки одинарной точности, вы не можете ожидать большей точности. С двойной точностью вы можете найти точность до 16. Вы не должны доверять разнице между двумя числами, если она не больше мантиссы:
Для получения дополнительной информации см. эти примеры … или таблица в этой статье …