• ACM浮点数相关的陷阱


    误差修正

    因为被计算机表示浮点数的方式所限制,CPU在进行浮点数计算时会出现误差。如执行0.1 + 0.2 == 0.3结果往往为false,在四则运算中,加减法对精度的影响较小,而乘法对精度的影响更大,除法的对精度的影响最大。所以,在设计算法时,为了提高最终结果的精度,要尽量减少计算的数量,尤其是乘法和除法的数量。

    浮点数与浮点数之间不能直接比较,要引入一个eps常量。eps是epsilon()的简写,在数学中往往代表任意小的量。在对浮点数进行大小比较时,如果他们的差的绝对值小于这个量,那么我们就认为他们是相等的,从而避免了浮点数精度误差对浮点数比较的影响。eps在大部分题目时取1e-8就够了,但要根据题目实际的内容进行调整。

    模板代码

    // sgn返回x经过eps处理的符号,负数返回-1,正数返回1,x的绝对值如果足够小,就返回0。
    const double eps = 1e-8;
    int sgn(double x) { return x < -eps ? -1 : x > eps ? 1 : 0; }
    整型比较 等价的浮点数比较
    a == b sgn(a - b) == 0
    a > b sgn(a - b) > 0
    a >= b sgn(a - b) >= 0
    a < b sgn(a - b) < 0
    a <= b sgn(a - b) <= 0
    a != b sgn(a - b) != 0

    输入输出

    scanf输入浮点数时,double的占位符是%lf,但是浮点数doubleprintf系列函数中的标准占位符是%f而不是%lf,使用时最好使用前者,因为虽然后者在大部分的计算机和编译器中能得到正确结果,但在有些情况下会出错(比如在POJ上)。

    开方

    当提供给C语言中的标准库函数double sqrt (double x)x为负值时,sqrt会返回nan,输出时会显示成nan-1.#IND00(根据系统的不同)。在进行计算几何编程时,经常有对接近零的数进行开方的情况,如果输入的数是一个极小的负数,那么sqrt会返回nan这个错误的结果,导致输出错误。解决的方法就是将sqrt包装一下,在每次开方前进行判断。

    示例代码

    double mysqrt(double x) { return max(0.0, sqrt(x)); }
    

    负零

    大部分的标程的输出是不会输出负零的,如下面这段程序:

    int main() {
        printf("%.2f
    ", -0.0000000001);
        return 0;
    }
    

    会输出-0.00。有时这样的结果是错误的,所以在没有Special Judge的题目要求四舍五入时,不要忘记对负零进行特殊判断。

    但有的标程也不会进行这样的特殊判断,所以在WA时不要放弃摸索。

  • 相关阅读:
    python3中try异常调试 raise 异常抛出
    基于 k8s-搭建 Kubernetes 的 web 管理界面
    PostgreSQL SERIAL创建自增列
    C++之同名覆盖、多态
    golang实现路由中间件middleware
    fastjson源码分析之序列化
    AJPFX实践 java实现快速排序算法
    AJPFX关于IO流的简单总结
    AJPFX关于多态中的动态绑定和静态绑定的总结
    关于java的arrays数组排序示例AJPFX的分享
  • 原文地址:https://www.cnblogs.com/pearfl/p/10733192.html
Copyright © 2020-2023  润新知