在最近的工作中,遇到一个BUG,本应是1200的一个变量,结果却变成了1199,找了一会,发现是由于Double的存储引起的。

问题简化如下:

vard: Double;
begintryd := 1.2;Writeln(Trunc(d * 1000));Readln;excepton E: Exception doWriteln(E.ClassName, ': ', E.Message);end;
end.

运行结果如下:

结果并不是意料中的1200,而是1199。

这是由于浮点数在内存中的存储格式引发的问题,具体的可以点击看这篇文章

由此,发散思维,做了几组对比实验。代码如下:

vardTest: Double;
begin//实验1dTest := 1.2;Writeln('当dTest赋值为1.2,你以为的dTest: 1.2,');Writeln('实际内存中存的dTest: ' + Format('%.18f', [dTest]));Write('你以为Ceil(dTest * 1000) = 1201,但是Ceil(dTest * 1000) = ');Writeln(Ceil(dTest * 1000));Write('Trunc(dTest * 1000): ');Writeln(Trunc(dTest * 1000));Writeln('FloatToStr(dTest * 1000): ' + FloatToStr(dTest * 1000));Writeln('');//实验2dTest := 1.199999999999999960;Writeln('当dTest赋值为1.199999999999999960,你以为的dTest: 1.199999999999999960');Writeln('实际内存中存的dTest: ' + Format('%.18f', [dTest]));Write('你以为Ceil(dTest * 1000) = 1200,但是Ceil(dTest * 1000) = ');Writeln(Ceil(dTest * 1000));Write('Trunc(dTest * 1000): ');Writeln(Trunc(dTest * 1000));Writeln('FloatToStr(dTest * 1000): ' + FloatToStr(dTest * 1000));Writeln('');//实验3dTest := 1.19999999999999990;Writeln('当dTest赋值为1.19999999999999990,你以为的dTest: 1.19999999999999990');Writeln('实际内存中存的n: ' + Format('%.18f', [dTest]));Write('你以为Ceil(dTest * 1000) = 1200,但是Ceil(dTest * 1000) = ');Writeln(Ceil(dTest * 1000));Write('Trunc(dTest * 1000): ');Writeln(Trunc(dTest * 1000));Writeln('FloatToStr(dTest * 1000): ' + FloatToStr(dTest * 1000));Writeln('');//实验4dTest := 1.199;Writeln('当dTest赋值为1.199,你以为的dTest: 1.199');Writeln('实际内存中存的n: ' + Format('%.18f', [dTest]));Write('你以为Ceil(dTest * 1000) = 1200,但是Ceil(dTest * 1000) = ');Writeln(Ceil(dTest * 1000));Write('Trunc(dTest * 1000): ');Writeln(Trunc(dTest * 1000));Writeln('FloatToStr(dTest * 1000): ' + FloatToStr(dTest * 1000));Writeln('');//实验5dTest := 0.2;Writeln('当dTest赋值为0.2,你以为的dTest: 0.2');Writeln('实际内存中存的dTest: ' + Format('%.18f', [dTest]));Write('你以为Ceil(dTest * 1000) = 200,但是Ceil(dTest * 1000) = ');Writeln(Ceil(dTest * 1000));Write('Trunc(dTest * 1000): ');Writeln(Trunc(dTest * 1000));Writeln('FloatToStr(dTest * 1000): ' + FloatToStr(dTest * 1000));Writeln('');//实验6dTest := 11.2;Writeln('当dTest赋值为11.2,你以为的dTest: 11.2');Writeln('实际内存中存的dTest: ' + Format('%.18f', [dTest]));Write('你以为Ceil(dTest * 1000) = 11200,但是Ceil(dTest * 1000) = ');Writeln(Ceil(dTest * 1000));Write('Trunc(dTest * 1000): ');Writeln(Trunc(dTest * 1000));Writeln('FloatToStr(dTest * 1000): ' + FloatToStr(dTest * 1000));Writeln('');//实验7dTest := 111.2;Writeln('当dTest赋值为1111.2,你以为的dTest: 1111.2');Writeln('实际内存中存的dTest: ' + Format('%.18f', [dTest]));Write('你以为Ceil(dTest * 1000) = 1111200,但是Ceil(dTest * 1000) = ');Writeln(Ceil(dTest * 1000));Write('Trunc(dTest * 1000): ');Writeln(Trunc(dTest * 1000));Writeln('FloatToStr(dTest * 1000): ' + FloatToStr(dTest * 1000));Readln;
end.

结果如下:

在Delphi中使用Ceil和Trunc对浮点数取整结果可能会出乎你的意料。当double存储时没有精度问题时,使用Ceil和Trunc函数没有问题,当有精度丢失时,使用Ceil和Trunc需要注意。

Delphi 中关于Double类型精度以及使用Ceil和Trunc取整引发的问题相关推荐

  1. double类型精度丢失问题以及解决方法

    double类型精度丢失问题: (1)加法运算. public static void main(String[] args) {double number1 = 1;double number2 = ...

  2. delphi 对金额double类型向上取整,保留小数位

    delphi 对金额double类型向上取整,保留小数位 //新保留小数位,只要后面有多余的数据,则进位 function NewRoundTo(value: Double; ws: Integer) ...

  3. java中double类型精度丢失问题及解决方法

    点击上方"方志朋",选择"设为星标" 回复"666"获取新整理的面试文章 来源: https://blog.csdn.net/yacolsp ...

  4. double operator[](int i)_java中double类型精度丢失问题及解决方法

    原文链接:https://blog.csdn.net/yacolspace/article/details/78287394 double类型数据加减操作精度丢失问题 今天在项目中用到double类型 ...

  5. Java中double类型精度丢失的问题_double类型数据加减操作精度丢失解决方法_BigDecimal取整

    BigDecimal在用double做入参的时候,二进制无法精确地表示十进制小数,编译器读到字符串"0.0000002"和"1.0000002"之后,必须把它转 ...

  6. Double类型精度问题引起的错误

    场景说明 研发同事让把某个double类型字段的值四舍五入保留2位小数,mysql中round(col,2)可以实现四舍五入并且保留2位小数,但是神奇的事情发生了:发现有的四舍五入是正确的,而有的不是 ...

  7. Java中的double类型数据存储探析

    一.double类型的存储表示 Java的浮点类型表示完全按照IEEE754标准(Standards of IEEE 754 floating point numbers),有兴趣可以上IEEE标准网 ...

  8. Delphi中的指针类型

    首先讲讲指针类型在delphi中是怎么定义的: 指针类型的定义语法 type <指针类型标识符>=^<基类型>: 指针指向动态变量的类型是由^符后的基类型来标识,^符号也就是指 ...

  9. java double 类型_关于Java中的double类型数据

    在初学Java的时候,一般我们都会从基本的数据类型开始学习,而在基本数据类型中,我认为double类型是比较难理解的,并且在以后的学习或工作中,在double类型数据这遇到的坑也是极多的.例如下面的这 ...

最新文章

  1. ios -使用NSLayoutConstraint实现多个view等宽等高等间距
  2. NIO中的SelectionKey
  3. matlab中读文件的行数_Matlab中读取txt文件的几种方法
  4. 台式电脑可以连接手机热点吗_移动硬盘可以连接手机吗
  5. nginx负载均衡的五种方式
  6. JAVA16版本.JDK16即将发布,你准备好了吗?
  7. 接二手java项目需要什么资料_师妹问双非本科如何进BAT,我告诉她Java后端路线...
  8. 天气预测频繁2项集_官宣!今冬冷空气偏强 北方或现大范围低温雨雪天气
  9. java 操作位_Java位运算符
  10. 安卓按键命令库教程(紫猫版续)
  11. 视频编码中的PAFF和MBAFF的区别
  12. WZ安卓面试宝典App
  13. MySQL业务账号需要哪些权限_MySQL 日常运维业务账号权限的控制
  14. Pandas:利用Styler对象设置Series、Dataframe在Jupyter Notebook中的输出样式(1)——基础接口
  15. java物流管理系统_基于java的物流管理系统
  16. 学生信息管理系统V2.0
  17. 关于nomogram核心函数的time.inc函数的设定
  18. 2018/8/22部分算法总结 二维几何常用算法
  19. 用IMAP4访问Exchange邮箱
  20. Siamese Network (应用篇5) :孪生网络用于跟踪 CVPR2016

热门文章

  1. js常见的的6种继承方式
  2. 无线通讯 - 5G芯片和5G模组区别
  3. playsound 模块解决 UnicodeDecodeError 异常
  4. 如何使用Django和Celery为Web构建进度栏
  5. 学姐解答秋招求职之-网申之后宣讲会有必要去吗?
  6. 关于gp数据库的DK(GP)
  7. 解决Win7 SP1提示缺少组件无法安装问题
  8. PHP函数处理字符串大全
  9. 炒股技术——指数,K线形态,分时,消息,行业板块,打板
  10. 永硕e盘php,永硕E盘特效代码集萃