如何解决 C++中三角函数和计算带来的误差?

2016-02-21 22:17:39 +08:00
 skywatcher
double a = sqrt(2)/2 = 0.70710678118654746
double b = acos(a) = 1.5707963267948966
double c = sin(b) = 0.70710678125004089

如何减小 a 和 c 之间的误差?

1812 次点击
所在节点    C
17 条回复
Neveroldmilk
2016-02-21 22:58:58 +08:00
不用减小,只需要设立一个很小的 double 数值来判断两个 double 值是否相等。这是对比浮点数的基本操作。
6god
2016-02-21 23:05:13 +08:00
Numerical method 中的 loss of significance. 别问我具体是啥 只知道章节 不会用啊
Changxu
2016-02-21 23:09:58 +08:00
误差可能来自两方面: 1 、函数泰勒级数展开项不够多,这个可以改写函数,使用更多的级数来展开; 2 、 double 类型运算 /精度误差,请参考 IEEE 754 标准,这个误差就得使用高精度运算等来解决了
MCVector
2016-02-21 23:35:28 +08:00
试试 long double? sqrt(2.0L)
skywatcher
2016-02-21 23:43:31 +08:00
@Neveroldmilk 我知道可以自己根据精度写个 equal 函数,但是我想要更高的精度
skywatcher
2016-02-21 23:44:20 +08:00
@MCVector 提问之前已测试过无效
skywatcher
2016-02-21 23:46:59 +08:00
@Changxu 3q ,查了计算精度和编译器有关,不知道能否有效解决。你之前用过?
mickeyandkaka
2016-02-21 23:47:49 +08:00
libgmp
skywatcher
2016-02-21 23:48:44 +08:00
@6god 我查查
SoloCompany
2016-02-22 01:35:30 +08:00
http://stackoverflow.com/questions/4818573/accuracy-of-long-double-sqrt

撸主你有点懒啊,我还是帮你一下吧,用 std::sqrt 可破
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 ,但是没有用过这个)
Changxu
2016-02-22 12:47:01 +08:00
@skywatcher 没,我使用过程中对精度要求没有那么高,一般误差在 1e-7 以下就可以忽略了
ilotuo
2016-02-22 13:13:15 +08:00
自己实现一个泰勒展开~
mko0okmko0
2016-02-22 13:14:52 +08:00
编译器中与浮点精度有关的参数,你的程式码用 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 一样.
但有很多库或是变换方法可计算指定位数舍入 /方式,或是科学库近乎无损的.
你可以找无损计算科学库.然后注意这些库的编译参数条件(就上面那些还有更多)的指定要求.
skywatcher
2016-02-22 13:54:26 +08:00
@6god 看了一下,通过变换表达式来避免误差,很有意思!
skywatcher
2016-02-22 14:17:02 +08:00
@mko0okmko0
@starqoq
@mickeyandkaka

非常感谢,这几个库都已经能达到很高的精度了!
skywatcher
2016-02-22 14:23:05 +08:00
非常感谢!
@SoloCompany 表示 std::sqrt 并未带来优势
@MCVector long double 确实改进了(之前输入参数没注意)

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/258068

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX