double a = sqrt(2)/2 = 0.70710678118654746
double b = acos(a) = 1.5707963267948966
double c = sin(b) = 0.70710678125004089
如何减小 a 和 c 之间的误差?
1
Neveroldmilk 2016-02-21 22:58:58 +08:00
不用减小,只需要设立一个很小的 double 数值来判断两个 double 值是否相等。这是对比浮点数的基本操作。
|
2
6god 2016-02-21 23:05:13 +08:00 via iPad
Numerical method 中的 loss of significance. 别问我具体是啥 只知道章节 不会用啊
|
3
Changxu 2016-02-21 23:09:58 +08:00
误差可能来自两方面: 1 、函数泰勒级数展开项不够多,这个可以改写函数,使用更多的级数来展开; 2 、 double 类型运算 /精度误差,请参考 IEEE 754 标准,这个误差就得使用高精度运算等来解决了
|
4
MCVector 2016-02-21 23:35:28 +08:00
试试 long double? sqrt(2.0L)
|
5
skywatcher OP @Neveroldmilk 我知道可以自己根据精度写个 equal 函数,但是我想要更高的精度
|
6
skywatcher OP @MCVector 提问之前已测试过无效
|
7
skywatcher OP @Changxu 3q ,查了计算精度和编译器有关,不知道能否有效解决。你之前用过?
|
8
mickeyandkaka 2016-02-21 23:47:49 +08:00
libgmp
|
9
skywatcher OP @6god 我查查
|
10
SoloCompany 2016-02-22 01:35:30 +08:00
http://stackoverflow.com/questions/4818573/accuracy-of-long-double-sqrt
撸主你有点懒啊,我还是帮你一下吧,用 std::sqrt 可破 |
11
starqoq 2016-02-22 09:55:15 +08:00
也可以使用符号计算库。
http://www.ginac.de/tutorial/#How-to-use-it-from-within-C_002b_002b (我用过 python 的 sympy ,但是没有用过这个) |
12
Changxu 2016-02-22 12:47:01 +08:00
@skywatcher 没,我使用过程中对精度要求没有那么高,一般误差在 1e-7 以下就可以忽略了
|
13
ilotuo 2016-02-22 13:13:15 +08:00
自己实现一个泰勒展开~
|
14
mko0okmko0 2016-02-22 13:14:52 +08:00 1
编译器中与浮点精度有关的参数,你的程式码用 gcc 编译时试着加入看看?
-mfpmath=sse -msseregparm -m128bit-long-double -mlong-double-128 -mpc80 -mrecip=? -ffloat-store -fexcess-precision=? -ffast-math=? -fno-math-errno -fsingle-precision-constant https://gcc.gnu.org/onlinedocs/gcc-4.9.3/gcc/Floating-point-implementation.html#Floating-point-implementation https://gcc.gnu.org/onlinedocs/gcc-4.9.3/gcc/i386-and-x86-64-Options.html#i386-and-x86-64-Options 另外提示你,C(++)浮点计算是有明确规范舍入误差的,就像 php/js 一样. 但有很多库或是变换方法可计算指定位数舍入 /方式,或是科学库近乎无损的. 你可以找无损计算科学库.然后注意这些库的编译参数条件(就上面那些还有更多)的指定要求. |
15
skywatcher OP @6god 看了一下,通过变换表达式来避免误差,很有意思!
|
16
skywatcher OP |
17
skywatcher OP |