不知道限制 sin(x) 公式循环
No idea for limit the sin(x) formula loop
使 c/++ 函数计算 sin(x)
通过公式引用;
但我不知道在哪里停止无穷和,我不想要快速回答的图书馆。我想成功。
我很好地制作了阶乘函数。 (事实()函数)
double sin(int x) {
int tp=0;
for(int k=1; ;k++)
{
tp+=pow(-1,k)*pow(x,2*k+1)/fact(2*k+1);
}
return tp;
}
你需要的是一个 epsilon 值,当我比我们要停止的那个数字更准确时你说的一个值。它看起来像 if(abs(prev_ans - cur_ans) < epsilon) break;
用数学术语来说,序列的 n
和 n+1
部分总和变化很小,以至于继续序列不会产生任何更理想的精度
当计算出的值 (tp
) 变化不大时,您应该停止。检查新计算值与旧值的差异,如果绝对差异(为此使用 fabs()
)小于 epsilon(您定义的),则停止迭代。
当你停下来的时候,你会得到一个近似的罪恶结果。
此外,int tp=0;
对我来说似乎不正确。当 k
为 0 时,你应该用公式结果初始化它。更重要的是,它应该是 double
类型,因为 int
是整数。
此外,值 x
不仅必须在 弧度 中,而且通常还必须在 -π 到 +π 范围内。
发布以供参考,这是我的版本,它使用级数扩展的各个组件的渐进式计算,而不是调用外部 O(n)
阶乘函数:
double mysin(double x)
{
int sign = 1;
int iteration = 1;
double xn = x;
double factorial = 1.0;
double result = 0.0;
double delta;
while (iteration < 31) {
delta = xn / factorial;
result += sign * delta;
xn *= x * x;
sign = -sign;
factorial *= ++iteration;
factorial *= ++iteration;
}
return result;
}
根据我的测试,如果 fabs(delta)
变得太小,那么提早跳出似乎不会在准确性(或性能)方面有任何显着优势,除非 x
的初始值也是很小。
在我们继续之前,您必须对 return 类型和累加使用 double
,否则结果将被(严重)截断。
当添加变化项不改变当前累加求和值时应停止,即存在下溢。这发生在:
The magnitude of the change term is less than the value of the lowest binary digit of the accumulator.
要检查这一点,提取浮点数的 指数 很有用。 This SO post 提供了一个有用的函数:frexp
.
然后我们可以检查变化项的指数是否小于累加器的指数减去尾数[=50]中的位数=] double
类型(52 位)。如果您需要了解更多信息,请搜索 IEEE 浮点格式.
提高数值精度和速度的另一点:让我们检查连续项之间的关系:
因此,与其从头开始计算每一项(使用幂函数和阶乘函数),我们可以边计算边迭代计算每一项。
示例代码:
// 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
)
我运行循环8次,如果你改善循环时间,它接近真实值。感谢@Sreeram TP
double sin(int x) {
int tp=0;
for(int k=1;k<8 ;k++)
{
tp+=pow(-1,k)*pow(x,2*k+1)/fact(2*k+1);
}
return tp;
}
使 c/++ 函数计算 sin(x)
通过公式引用;
但我不知道在哪里停止无穷和,我不想要快速回答的图书馆。我想成功。 我很好地制作了阶乘函数。 (事实()函数)
double sin(int x) {
int tp=0;
for(int k=1; ;k++)
{
tp+=pow(-1,k)*pow(x,2*k+1)/fact(2*k+1);
}
return tp;
}
你需要的是一个 epsilon 值,当我比我们要停止的那个数字更准确时你说的一个值。它看起来像 if(abs(prev_ans - cur_ans) < epsilon) break;
用数学术语来说,序列的 n
和 n+1
部分总和变化很小,以至于继续序列不会产生任何更理想的精度
当计算出的值 (tp
) 变化不大时,您应该停止。检查新计算值与旧值的差异,如果绝对差异(为此使用 fabs()
)小于 epsilon(您定义的),则停止迭代。
当你停下来的时候,你会得到一个近似的罪恶结果。
此外,int tp=0;
对我来说似乎不正确。当 k
为 0 时,你应该用公式结果初始化它。更重要的是,它应该是 double
类型,因为 int
是整数。
此外,值 x
不仅必须在 弧度 中,而且通常还必须在 -π 到 +π 范围内。
发布以供参考,这是我的版本,它使用级数扩展的各个组件的渐进式计算,而不是调用外部 O(n)
阶乘函数:
double mysin(double x)
{
int sign = 1;
int iteration = 1;
double xn = x;
double factorial = 1.0;
double result = 0.0;
double delta;
while (iteration < 31) {
delta = xn / factorial;
result += sign * delta;
xn *= x * x;
sign = -sign;
factorial *= ++iteration;
factorial *= ++iteration;
}
return result;
}
根据我的测试,如果 fabs(delta)
变得太小,那么提早跳出似乎不会在准确性(或性能)方面有任何显着优势,除非 x
的初始值也是很小。
在我们继续之前,您必须对 return 类型和累加使用 double
,否则结果将被(严重)截断。
当添加变化项不改变当前累加求和值时应停止,即存在下溢。这发生在:
The magnitude of the change term is less than the value of the lowest binary digit of the accumulator.
要检查这一点,提取浮点数的 指数 很有用。 This SO post 提供了一个有用的函数:frexp
.
然后我们可以检查变化项的指数是否小于累加器的指数减去尾数[=50]中的位数=] double
类型(52 位)。如果您需要了解更多信息,请搜索 IEEE 浮点格式.
提高数值精度和速度的另一点:让我们检查连续项之间的关系:
因此,与其从头开始计算每一项(使用幂函数和阶乘函数),我们可以边计算边迭代计算每一项。
示例代码:
// 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
)
我运行循环8次,如果你改善循环时间,它接近真实值。感谢@Sreeram TP
double sin(int x) {
int tp=0;
for(int k=1;k<8 ;k++)
{
tp+=pow(-1,k)*pow(x,2*k+1)/fact(2*k+1);
}
return tp;
}