Console.WriteLine(7.88 + 5.00 - 12.88); 结果为True还是False?

Console.WriteLine(7.88 + 5.00 == 12.88);结果是什么呢?

结果为False,是的哦,为什么会这样呢?

分析

用"=="来比较两个double应该相等的类型,返回真值完全是不确定的。计算机对浮点数的进行计算的原理是只保证必要精度内正确即可,例如:double a=0.9+0.2;那么只能保证小数点后1位这个精度是正确的,计算机计算这个加法的结果a的值可能是1.100000001,也可能是1.100000002也可能就是1.1,也就是说计算机计算后并不保证0.1以下各位得到的都是正确的,所以直接用==进行比较是不可行的。
我们知道数据在电脑中是以1或0来存储的

下面是64位二进制数:
0100000001000111001101101101001001001000010101110011000100100011

作为Double,是这样分开的:

  • 标志(正负数): 0
  • 次方数: 10000000100 binary = 1028 次方
  • 尾数(精度): 0111001101101101001001001000010101110011000100100011

因此一个正常的数字表达为
(-1)0 x 10111001101101101001001001000010101110011000100100011 (binary) x 21028-1023
which is more simply represented as
1.0111001101101101001001001000010101110011000100100011 (binary) x 25
or
101110.01101101101001001001000010101110011000100100011

所以, 比如象 46.42829231507700882275457843206822872161865234375, 在net中会显示为46.428292315077 或者 46.428292315077009

由上面分析的原因可以看出平时我们写的:

double x = 0.1d;

x其实不等同于0.1,有个能等于0.132323或其他,自然不难得出3.65d+0.05d != 3.7d

但有时候我们这样写程序的时候:

using System;

class Test
{
     static void Main(string[] args)
    {
      float   f = Sum (0.1f, 0.2f);
        float g = Sum (0.1f, 0.2f);
        Console.WriteLine (f==g);

    }
   
    static float Sum (float f1, float f2)
    {
        return f1+f2;
    }
}
却发现结果为true,其实在我们编译程序的时候JIT为我们做了部分优化

解决办法

比较两个double数是否相等应看其相减的绝对值是否小于某一数值,此值一般低于两数精确度

例如:Console.WriteLine(Math.Abs(7.88 + 5.00 - 12.88)<0.001);

有兴趣的朋友可以去参考:

http://www.yoda.arachsys.com/csharp/floatingpoint.html

时间: 2024-09-20 17:53:47

Console.WriteLine(7.88 + 5.00 - 12.88); 结果为True还是False?的相关文章

Console.WriteLine()有那12种构造参数

问题描述 麻烦各位高手说详细点 解决方案 解决方案二: 解决方案三:引用1楼sandy945的回复: http://msdn.microsoft.com/zh-cn/library/system.console.writeline(VS.80).aspx 看帮助啊解决方案四:重载列表在你输入左括号的时候就会显示,你可以用"上""下"方向键来查看.解决方案五:你鼠标放在那,就可以显示出来定义.

如何禁用Console.WriteLine等输出

问题描述 项目引用了别人写的一个类库,里面很多Console.WriteLine,我这本身也是要用Console输入输出一些东西这样控制台里显示就混乱了,现在不知道该怎么才能教你用引用的类库里的控制台输出 解决方案 解决方案二:让那个别人把console都去掉.解决方案三:你就不要Console了,你log吧--解决方案四:自定义一个TextWriter,对WriteLine方法的调用进行过滤,如果不是你需要的内容就不要输出,如果是就输出.然后用Console.SetOut方法替换默认的输出为你

识别-C# 使用LibusbDotNet实现usb热插拔遇到的异常

问题描述 C# 使用LibusbDotNet实现usb热插拔遇到的异常 我想实现USB连接后,数据通信过程中插拔USB,软件自动识别USB后,能够自动连接并继续发送数据,软件不死机. 但是,往往插拔几次后会出现" Safe handle has been closed Exception"异常 下面是识别USB的代码 我试了下,先关闭USB设备后关闭发送线程标志位,和先关闭发送线程标志位后关闭USB设备都会出现这种问题, 下面是打印的调试信息,通过调试信息发现,在识别到USB断开之前,

异步调用Web服务

web|web服务|异步 //////////////////////////////////////////////////////////////////////////////////Author: stardicky ////E-mail: stardicky@hotmail.com ////QQNumber: 9531511 ////CompanyName: Ezone International ////Class: HBS-0308 ////title: 异步调用Web服务 ///

Lambda应用设计模式

原文:Lambda应用设计模式 前言 在使用 Lambda 表达式时,我们常会碰到一些典型的应用场景,而从常用场景中抽取出来的应用方式可以描述为应用模式.这些模式可能不全是新的模式,有的参考自 JavaScript 的设计模式,但至少我看到了一些人为它们打上了名字标签.无论名字的好与坏,我还是决定给这些模式进行命名,至少这些名字很具有描述性.同时我也会给出这些模式的可用性.强大的部分和危险的部分.提前先说明:绝大多数模式是非常强大的,但有可能在代码中引入些潜在的 Bug.所以,慎用. 目录导航

wcf-C#如何编写检测网络是否连接的windows服务?

问题描述 C#如何编写检测网络是否连接的windows服务? 如题,本人没有做过windows服务编程,也是C#新手,最近想做一个检测网络连接状态的服务,如果网络已连接,就启动本机一个指定的程序?请教下这个功能如何实现,最好能有代码 解决方案 win32 API函数的做法: 要用的函数:InternetGetConnectedState 函数原形:BOOL InternetGetConnectedState(LPDWORD lpdwFlags,DWORD dwReserved); 参数lpdwF

C#网络应用编程基础练习题与答案(三)

编程|网络 1. 编写一个控制台应用程序,完成下列功能. 1) 创建一个类,用无参数的构造函数输出该类的类名. 2) 增加一个重载的构造函数,带有一个string类型的参数,在此构造函数中将传递的字符串打印出来. 3) 在Main方法中创建属于这个类的一个对象,不传递参数. 4) 在Main方法中创建属于这个类的另一个对象,传递一个字符串"This is a string.". 5) 在Main方法中声明类型为这个类的一个具有5个对象的数组,但不要实际创建分配到数组里的对象. 6) 写

link用循环计算两个日期之间有多少工作日

问题描述 link用循环计算两个日期之间有多少工作日 用循环计算两个日期之间有多少工作日,link怎么实现?用takewhile怎么代替while? 解决方案 不考虑过节和轮休,写一个给你 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace ConsoleApplication1 { class P

【原创】开源Math.NET基础数学类库使用(17)C#计算矩阵条件数

               本博客所有文章分类的总目录:[总目录]本博客博文总目录-实时更新  开源Math.NET基础数学类库使用总目录:[目录]开源Math.NET基础数学类库使用总目录 上个月对Math.NET的基本使用进行了介绍,主要内容有矩阵,向量的相关操作,解析数据格式,数值积分,数据统计,相关函数,求解线性方程组以及随机数发生器的相关内容.这个月接着深入发掘Math.NET的各种功能,并对源代码进行分析,使得大家可以尽可能的使用Math.NET在.NET平台下轻易的开发数学计算相