• dnan的好处2


    恕我直言,这是更好的方法,甚至不是异常,而是错误.
    只要你有NaN值,程序就是无用和损坏的.
    只要变量变为NaN,就应该抛它,而不仅是在操作时.
    如下成立时它应该抛:
    1,初化值为NaN并在操作中使用
    2,在初化外,置值为NaN
    3,从函数返回NaN
    这解决所有问题,因为:
    你永远不会在整个程序中传播NaN值,从而更易追踪它.
    NaN严格告诉你,在使用某些值前,是错误的
    无法有效地解决它,即你必须实际修复所有NaN.

    D允许使用std.math.hardware.FloatingPointControl接口启用浮点异常.
    当然,这些是硬件异常,因此你获得SIGFPE而不是带回溯的抛错误.要转换为D错误,需要安装信号处理器,就像etc.linux.memoryerror那样(或Windows上的等价物)

    可惜,似乎在实践中不管用,因为仅在创建NaN时,而不是在传播时触发"无效"浮点异常.由于是在编译时而不是运行时创建默认初化float/double变量的初始NaN值,因此不会触发异常.
    示例:

    import std.math.hardware;
    
    float div(float x, float y)
    {
        return x / y;
    }
    
    void main()
    {
        FloatingPointControl fpctrl;
        fpctrl.enableExceptions(FloatingPointControl.severeExceptions);
    
        float f = float.nan; // ok -无异常
        float g = div(0.0f, 0.0f); // SIGFPE崩溃.
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    NaN总是错误的.0.0无处不在.如果从不查看输出,则都不会注意其中错误.
    你需要分析数据流.我没有把DFA放在前端,因为这会使它变慢而无好处.
    不必害怕在输出中获得NaN.相反应该很高兴,因为你*知道*错误.
    D是帮助程序员创建正确,健壮和无错误程序的工具.
    检查整

    你正在推广使用结构初值作为特征,而不是基本类型的初值.
    不同在它必须为有意设置的字段值,并且仅针对该字段值.它不是默认值.

    double compute_pop ()
       {
          double pop;
          // 忽略实现,偶遇nan
          pop = sqrt (-1.);
          pop += 0.;
          return pop;
       }
    
       int main ()
       {
          auto pop = compute_pop ();
          if (pop < .5)
             writeln ("不下雨");
          else
             writeln ("会下雨");
          return 0;
       }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    前几天我玩isNaN.用它来检查访问函数中的初化,来缓存昂贵计算.在注意到发布版本出现故障前,这非常有效.过了一段时间,我才发现ldc为发布版本,提供了fastmath选项,它假定没有NaN,而这导致isNaN错误工作.
    示例:

    import std;
    void main()
    {
        assert(isNaN(double.nan));
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    --ffast-math -O选项结合ldc编译.
    isnan实现:

    bool isNaN(X)(X x) @nogc @trusted pure nothrow
    if (isFloatingPoint!(X))
    {
        version (all)
        {
            return x != x;
        }
        else
        {
            /*
             历史背景保存的代码.至少在英特尔,简单的测试`x!=x`使用一条在一条指令中运行循环的`(ucomiss/ucomisd)`专用指令.`80`位和`128`位的代码更大,但仍小于下面基于整数的方法
            */
         // 略...
       }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    这不仅与Walter的理解相悖,而且与IEEE754标准相悖.这是一篇更详细文章:小心快速数学
    具有快速数学的LLVM假定所有浮点操作数都是有限的,即可在编译时优化x!=xfalse.足够聪明优化器,如果识别出NaN的位模式,原则上可优化检查位模式.

    UDA等的好处之一是,可用它们来选择LLVM可执行的特定优化,而无需选择明显危险的优化.
    1,2,3
    不要滥用异常
    0<=NaN.确实,有时0是相等的.但它*不可能*更好.
    顺便,十六进制数据没有NaN值.但经常初化它为:0xDEADBEEF
    这在野外不太可能.因此,当转储十六进制数据且有DEADBEEF时,表明有未初化数据.
    我既用它在返回给调用者前,初化malloc的数据,并为其设置释放后数据.它在清理未初化分配数据释放后使用错误方面非常有效.使用0x00远没有它有效.

  • 相关阅读:
    Docker-harbor私有仓库部署与管理
    MAUI+Blazor混合应用开发示例
    Python去除中文文本中的特殊字符
    node.js中express框架cookie-parser包设置cookie的问题
    【数据结构(邓俊辉)学习笔记】向量02——动态空间管理
    算法通关村第六关-青铜挑战树
    Spring原理-IOC和AOP
    源代码加密技术的区别
    数据库缓存服务——NoSQL之Redis配置与优化
    InnoDB中外键与锁
  • 原文地址:https://blog.csdn.net/fqbqrr/article/details/126538690