在最近的工作中,遇到一个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. Wireshark使用技巧:提取VOIP通话中的音频流
  2. JSP简单标签带属性开发
  3. tf.expand_dims() 的用法
  4. POJ 2217:Secretary(后缀数组)
  5. 沈阳工程 c语言题库,2017年沈阳航空航天大学航空航天工程学部823C语言程序设计考研仿真模拟题...
  6. jaxb解析字符串xml_一个JAXB Nuance:字符串与枚举(受限制的XSD字符串)的枚举
  7. 大一计算机应用的实验报告,大一《计算机应用基础》实验报告1.doc
  8. btoa java,JavaScript用btoa和atob来编码解码Base64
  9. 字节跳动宣布要做全网搜索,百度真正的危机来了
  10. AD9361官方例程发送端数据流向
  11. word2013+endnotex8参考文献导入
  12. MCU_ZigBee协议栈相关函数总结
  13. Opencv之.convertTo
  14. linux bzip2压缩文件,linux bzip2命令压缩或解压缩bzip2文件
  15. CAD手机端怎么将DWG格式的图纸文件转换成PDF格式?
  16. essay--网络常用省略语大全(ZT)
  17. vue脚手架结构目录文件
  18. # Python第一节课
  19. EMV技术学习和研究(十一)QPBOC
  20. 前端和后端是如何实现交互的

热门文章

  1. 基于echarts实现根据鼠标移动轨迹更改曲线值或创建曲线
  2. 张家港python培训_张的英文_张翻译_张英语怎么说_海词词典
  3. fms系统服务器,fms运行在64-bit windows操作系统上_邮件服务器
  4. Day04-爬取豌豆荚app数据
  5. win7系统安装office 2010 visio 出现MSXML安装后依旧无法安装的解决办法
  6. 冲突域和广播域交换机模式的基础理解
  7. 凸优化学习笔记 10:凸优化问题
  8. 【游戏设计】从星露谷物语中学习游戏制作
  9. python绘图之matlibplot
  10. 辽宁学考服务器位置,辽宁学考考点查询软件