Прежде чем мы пойдем дальше, вы должны использовать double
для типов возврата и накопления, иначе результат будет (сильно) усечен.
Вы должны остановиться, когда добавление термина изменения не изменяет текущее накопленное значение суммирования, т. е. имеет место недополнение. Это происходит, когда:
Величина члена изменения меньше значения наименьшей двоичной цифры аккумулятора.
Чтобы проверить это, полезно извлечь показатель степени числа с плавающей запятой. Это сообщение SO предоставляет полезную функцию: frexp
.
Затем мы можем проверить, что показатель степени члена изменения меньше, чем показатель степени аккумулятора минус количество битов в мантиссе типа double
(52 бита). Если вам нужно узнать больше, выполните поиск по запросу Формат с плавающей запятой IEEE.
Еще один момент для улучшения числовой точности и скорости: давайте рассмотрим взаимосвязь между последовательными терминами:
![введите здесь описание изображения](https://i.stack.imgur.com/XZf9D.gif)
Таким образом, вместо того, чтобы вычислять каждый член с нуля (используя функции мощности и факториала), мы можем вычислять каждый член итеративно по мере продвижения.
Образец кода:
// best to use an existing C-library define for this, if exists
#define DBL_MANTISSA_BIT 52
double mysin_new(double x)
{
double term = x;
double sum = term;
for (int n = 1; ; n++) {
// next term in the series
term *= - (x / (2*n)) * (x / (2*n+1));
// check if the exponent is small enough for us to stop
int e_term, e_sum;
frexp(term, &e_term);
frexp(sum, &e_sum);
if (e_term <= e_sum - DBL_MANTISSA_BIT) break;
sum += term;
}
return sum;
}
Некоторые числовые тесты:
angle = 0.157080
library : 0.15643446504023086896f, 0011111111000100000001100000101101100111101010000101001101110101b
mysin_old: 0.15643446504023086896f, 0011111111000100000001100000101101100111101010000101001101110101b
mysin_new: 0.15643446504023089672f, 0011111111000100000001100000101101100111101010000101001101110110b
angle = 0.314159
library : 0.30901699437494739575f, 0011111111010011110001101110111100110111001011111110100101001111b
mysin_old: 0.30901699437494745126f, 0011111111010011110001101110111100110111001011111110100101010000b
mysin_new: 0.30901699437494739575f, 0011111111010011110001101110111100110111001011111110100101001111b
angle = 0.471239
library : 0.45399049973954674897f, 0011111111011101000011100010111000101011010001001101111000000000b
mysin_old: 0.45399049973954674897f, 0011111111011101000011100010111000101011010001001101111000000000b
mysin_new: 0.45399049973954674897f, 0011111111011101000011100010111000101011010001001101111000000000b
angle = 0.628319
library : 0.58778525229247313710f, 0011111111100010110011110010001100000100011101010101101001011110b
mysin_old: 0.58778525229247313710f, 0011111111100010110011110010001100000100011101010101101001011110b
mysin_new: 0.58778525229247313710f, 0011111111100010110011110010001100000100011101010101101001011110b
angle = 0.785398
library : 0.70710678118654746172f, 0011111111100110101000001001111001100110011111110011101111001100b
mysin_old: 0.70710678118654746172f, 0011111111100110101000001001111001100110011111110011101111001100b
mysin_new: 0.70710678118654746172f, 0011111111100110101000001001111001100110011111110011101111001100b
angle = 0.942478
library : 0.80901699437494745126f, 0011111111101001111000110111011110011011100101111111010010101000b
mysin_old: 0.80901699437494734024f, 0011111111101001111000110111011110011011100101111111010010100111b
mysin_new: 0.80901699437494734024f, 0011111111101001111000110111011110011011100101111111010010100111b
angle = 1.099557
library : 0.89100652418836778779f, 0011111111101100100000110010000000011101001111010010110001101100b
mysin_old: 0.89100652418836767676f, 0011111111101100100000110010000000011101001111010010110001101011b
mysin_new: 0.89100652418836767676f, 0011111111101100100000110010000000011101001111010010110001101011b
angle = 1.256637
library : 0.95105651629515353118f, 0011111111101110011011110000111000010011010001000101010011111111b
mysin_old: 0.95105651629515353118f, 0011111111101110011011110000111000010011010001000101010011111111b
mysin_new: 0.95105651629515353118f, 0011111111101110011011110000111000010011010001000101010011111111b
angle = 1.413717
library : 0.98768834059513777035f, 0011111111101111100110110010010010010100001011111110010001011100b
mysin_old: 0.98768834059513777035f, 0011111111101111100110110010010010010100001011111110010001011100b
mysin_new: 0.98768834059513777035f, 0011111111101111100110110010010010010100001011111110010001011100b
angle = 1.570796
library : 1.00000000000000000000f, 0011111111110000000000000000000000000000000000000000000000000000b
mysin_old: 1.00000000000000022204f, 0011111111110000000000000000000000000000000000000000000000000001b
mysin_new: 1.00000000000000000000f, 0011111111110000000000000000000000000000000000000000000000000000b
angle = 1.727876
library : 0.98768834059513777035f, 0011111111101111100110110010010010010100001011111110010001011100b
mysin_old: 0.98768834059513777035f, 0011111111101111100110110010010010010100001011111110010001011100b
mysin_new: 0.98768834059513777035f, 0011111111101111100110110010010010010100001011111110010001011100b
angle = 1.884956
library : 0.95105651629515364220f, 0011111111101110011011110000111000010011010001000101010100000000b
mysin_old: 0.95105651629515364220f, 0011111111101110011011110000111000010011010001000101010100000000b
mysin_new: 0.95105651629515375323f, 0011111111101110011011110000111000010011010001000101010100000001b
angle = 2.042035
library : 0.89100652418836789881f, 0011111111101100100000110010000000011101001111010010110001101101b
mysin_old: 0.89100652418836800983f, 0011111111101100100000110010000000011101001111010010110001101110b
mysin_new: 0.89100652418836800983f, 0011111111101100100000110010000000011101001111010010110001101110b
angle = 2.199115
library : 0.80901699437494745126f, 0011111111101001111000110111011110011011100101111111010010101000b
mysin_old: 0.80901699437494756229f, 0011111111101001111000110111011110011011100101111111010010101001b
mysin_new: 0.80901699437494756229f, 0011111111101001111000110111011110011011100101111111010010101001b
angle = 2.356194
library : 0.70710678118654757274f, 0011111111100110101000001001111001100110011111110011101111001101b
mysin_old: 0.70710678118654768376f, 0011111111100110101000001001111001100110011111110011101111001110b
mysin_new: 0.70710678118654757274f, 0011111111100110101000001001111001100110011111110011101111001101b
angle = 2.513274
library : 0.58778525229247324813f, 0011111111100010110011110010001100000100011101010101101001011111b
mysin_old: 0.58778525229247324813f, 0011111111100010110011110010001100000100011101010101101001011111b
mysin_new: 0.58778525229247324813f, 0011111111100010110011110010001100000100011101010101101001011111b
angle = 2.670354
library : 0.45399049973954685999f, 0011111111011101000011100010111000101011010001001101111000000010b
mysin_old: 0.45399049973954685999f, 0011111111011101000011100010111000101011010001001101111000000010b
mysin_new: 0.45399049973954691550f, 0011111111011101000011100010111000101011010001001101111000000011b
angle = 2.827433
library : 0.30901699437494750677f, 0011111111010011110001101110111100110111001011111110100101010001b
mysin_old: 0.30901699437494745126f, 0011111111010011110001101110111100110111001011111110100101010000b
mysin_new: 0.30901699437494745126f, 0011111111010011110001101110111100110111001011111110100101010000b
angle = 2.984513
library : 0.15643446504023097998f, 0011111111000100000001100000101101100111101010000101001101111001b
mysin_old: 0.15643446504023095223f, 0011111111000100000001100000101101100111101010000101001101111000b
mysin_new: 0.15643446504023095223f, 0011111111000100000001100000101101100111101010000101001101111000b
angle = 3.141593
library : 0.00000000000000012246f, 0011110010100001101001100000000000000000000000000000000000000000b
mysin_old: 0.00000000000000023566f, 0011110010110000111110110010110111010110111000110001010101001000b
mysin_new: 0.00000000000000023566f, 0011110010110000111110110010110111010110111000110001010101001001b
Новый адаптивный метод выигрывает в некоторых случаях по сравнению с исходным, рисует большинство из них и проигрывает в ряде других. (Обратите внимание, что предполагается, что библиотечный метод sin
абсолютно точен до точности double
)
person
meowgoesthedog
schedule
01.10.2017
int tp=0;
: ты уверен? - person BLUEPIXY   schedule 01.10.2017pow(x,2*k+1)/fact(2*k+1)
очень маленьким. Я рекомендую запустить цикл 8 раз, а не усложнять цикл некоторыми значениями эпсилон. - person Sreeram TP   schedule 01.10.2017int x
) не в радианах, верно? - person BLUEPIXY   schedule 01.10.2017