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

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

  •  1
     
  •   skywatcher Feb 21, 2016 2663 views
    This topic created in 3752 days ago, the information mentioned may be changed or developed.
    double a = sqrt(2)/2 = 0.70710678118654746 double b = acos(a) = 1.5707963267948966 double c = sin(b) = 0.70710678125004089 

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

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

    撸主你有点懒啊,我还是帮你一下吧,用 std::sqrt 可破
    starqoq
        11
    starqoq  
       Feb 22, 2016
    也可以使用符号计算库。

    http://www.ginac.de/tutorial/#How-to-use-it-from-within-C_002b_002b

    (我用过 python 的 sympy ,但是没有用过这个)
    Changxu
        12
    Changxu  
       Feb 22, 2016
    @skywatcher 没,我使用过程中对精度要求没有那么高,一般误差在 1e-7 以下就可以忽略了
    ilotuo
        13
    ilotuo  
       Feb 22, 2016
    自己实现一个泰勒展开~
    mko0okmko0
        14
    mko0okmko0  
       Feb 22, 2016   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 一样.
    但有很多库或是变换方法可计算指定位数舍入 /方式,或是科学库近乎无损的.
    你可以找无损计算科学库.然后注意这些库的编译参数条件(就上面那些还有更多)的指定要求.
    skywatcher
        15
    skywatcher  
    OP
       Feb 22, 2016
    @6god 看了一下,通过变换表达式来避免误差,很有意思!
    skywatcher
        16
    skywatcher  
    OP
       Feb 22, 2016
    @mko0okmko0
    @starqoq
    @mickeyandkaka

    非常感谢,这几个库都已经能达到很高的精度了!
    skywatcher
        17
    skywatcher  
    OP
       Feb 22, 2016
    非常感谢!
    @SoloCompany 表示 std::sqrt 并未带来优势
    @MCVector long double 确实改进了(之前输入参数没注意)
    About     Help     Advertise     Blog     API     FAQ     Solana     3168 Online   Highest 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 48ms UTC 12:16 PVG 20:16 LAX 05:16 JFK 08:16
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86