• 比较浮点数时,我被绊倒了


    • 📢欢迎点赞 :👍 收藏 ⭐留言 📝 如有错误敬请指正,赐人玫瑰,手留余香!
    • 📢本文作者:由webmote 原创
    • 📢作者格言:新的征程,我们面对的不是技术而是人心,人心不可测,海水不可量,唯有技术,才是深沉黑夜中的一座闪烁的灯塔 !

    1.简单的比较,预期的结果在这里插入图片描述

    一天,我在飞快的写代码,当然这个"飞快"我打上了引号, 因为手速奇快吗?并没有。

    我遇到一个非常普通的场景,对于码农多年的我老说,应该是小菜一碟了。

    然而,这次不一样,我被比较浮点数,绊倒了。

    简单描述下场景: 大概的业务逻辑是这样的, 在一个判断告警的逻辑里,需要判断某个值在小于0.9时,就进行告警动作。

    代码如下:

    bool IsAlarm(float a)
    {
     return a<0.9;
    }
    
    //不相干的业务逻辑,简化下。。。
    if(IsAlarm(a)){
      Console.WriteLine("嘀嘀嘀,报警了!");
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    写完了代码,就转给测试了,然后反馈说不该报警的时候报警了。

    这是什么鬼啊?

    Review了N遍代码,也找不到原因是啥。

    2.写单元测试

    由于业务场景复杂,又不方便调试,因此,实在打不开思路的我,开始折腾起单元测试。

    [Fact]
    public void TestAlarmSuccess()
    {
    	var a = 0.9F;
    	var ret = IsAlarm(a);
    	Assert.False(ret);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    元凶终于浮出了水面,竟然时浮点比较出了问题。经过反复确认和排查,的的确确是

    0.9F < 0.9
    
    • 1

    顺便说一嘴,这里用的是C#, 0.9F 是单精度浮点数,而 0.9 默认应该是 双精度浮点数。

    看到这里,聪明的你是不是恍然大悟了!

    如果你还是不明白, 那么跟着我再来探究探究其中的奥秘。

    3. 原因说明

    由于无知,我甚至跑到了github上提了一个issue,哦哦,大神给了我这样的解释。

    这是预期的结果! 更多的信息,可以参考: IEEE Standard for Floating-Point Arithmetic
    看下面的例子:

    float data = 0.9F;
    var firstComparisonValue = 0.9;
    var secondComparisonValue = 0.9F;
    Console.WriteLine(data < firstComparisonValue);
    // return true
    
    Console.WriteLine(data < secondComparisonValue);
    // return false
    
    Console.WriteLine(data == secondComparisonValue);
    // return true
    
    Console.WriteLine($"Data Value: {data.ToString("F99")}");
    Console.WriteLine($"First Comparison Value: >{firstComparisonValue.ToString("F99")}");
    Console.WriteLine($"Second Comparison Value: >{secondComparisonValue.ToString("F99")}"); ```
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    输出结果:
    True
    False
    True
    Data Value: 0,899999976158142089843750000000000000000000000000000000000000000000000000000000000000000000000000000
    First Comparison Value: 0,900000000000000022204460492503130808472633361816406250000000000000000000000000000000000000000000000
    Second Comparison Value: 0,899999976158142089843750000000000000000000000000000000000000000000000000000000000000000000000000000

    正如你看到的那样,double 类型的值是大于float类型的值的.

    总结

    比较数字的时候, 先强制转换成统一类型的数字,然后比较,才会得到你预期的结果。

    否则,你就需要了解更多的IEEE规范知识,要不然一不小心,就掉到了坑里。

    👓都看到这了,还在乎点个赞吗?

    👓都点赞了,还在乎一个收藏吗?

    👓都收藏了,还在乎一个评论吗?

  • 相关阅读:
    592. 分数加减运算 : 表达式计算入门题
    前端框架的演进之路:从静态网页到现代交互体验的探索
    艾美捷热转移稳定性检测试剂盒:简单、灵敏、均匀的荧光测定法
    【Hack The Box】linux练习-- Pandora
    图解KafkaConsumer SyncGroupRequest请求流程
    重生之我要学后端100--计算机网络部分概念(持续更新)
    【Java面试】谈谈你对HashMap的理解(Map接口)
    在c#中使用CancellationToken取消任务
    2.4.3 【MySQL】设置系统变量
    AlphaFold2源码解析(4)--模型架构
  • 原文地址:https://blog.csdn.net/webmote/article/details/134088271