Delphi 中关于Double类型精度以及使用Ceil和Trunc取整引发的问题
在最近的工作中,遇到一个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取整引发的问题相关推荐
- double类型精度丢失问题以及解决方法
double类型精度丢失问题: (1)加法运算. public static void main(String[] args) {double number1 = 1;double number2 = ...
- delphi 对金额double类型向上取整,保留小数位
delphi 对金额double类型向上取整,保留小数位 //新保留小数位,只要后面有多余的数据,则进位 function NewRoundTo(value: Double; ws: Integer) ...
- java中double类型精度丢失问题及解决方法
点击上方"方志朋",选择"设为星标" 回复"666"获取新整理的面试文章 来源: https://blog.csdn.net/yacolsp ...
- double operator[](int i)_java中double类型精度丢失问题及解决方法
原文链接:https://blog.csdn.net/yacolspace/article/details/78287394 double类型数据加减操作精度丢失问题 今天在项目中用到double类型 ...
- Java中double类型精度丢失的问题_double类型数据加减操作精度丢失解决方法_BigDecimal取整
BigDecimal在用double做入参的时候,二进制无法精确地表示十进制小数,编译器读到字符串"0.0000002"和"1.0000002"之后,必须把它转 ...
- Double类型精度问题引起的错误
场景说明 研发同事让把某个double类型字段的值四舍五入保留2位小数,mysql中round(col,2)可以实现四舍五入并且保留2位小数,但是神奇的事情发生了:发现有的四舍五入是正确的,而有的不是 ...
- Java中的double类型数据存储探析
一.double类型的存储表示 Java的浮点类型表示完全按照IEEE754标准(Standards of IEEE 754 floating point numbers),有兴趣可以上IEEE标准网 ...
- Delphi中的指针类型
首先讲讲指针类型在delphi中是怎么定义的: 指针类型的定义语法 type <指针类型标识符>=^<基类型>: 指针指向动态变量的类型是由^符后的基类型来标识,^符号也就是指 ...
- java double 类型_关于Java中的double类型数据
在初学Java的时候,一般我们都会从基本的数据类型开始学习,而在基本数据类型中,我认为double类型是比较难理解的,并且在以后的学习或工作中,在double类型数据这遇到的坑也是极多的.例如下面的这 ...
最新文章
- ios -使用NSLayoutConstraint实现多个view等宽等高等间距
- NIO中的SelectionKey
- matlab中读文件的行数_Matlab中读取txt文件的几种方法
- 台式电脑可以连接手机热点吗_移动硬盘可以连接手机吗
- nginx负载均衡的五种方式
- JAVA16版本.JDK16即将发布,你准备好了吗?
- 接二手java项目需要什么资料_师妹问双非本科如何进BAT,我告诉她Java后端路线...
- 天气预测频繁2项集_官宣!今冬冷空气偏强 北方或现大范围低温雨雪天气
- java 操作位_Java位运算符
- 安卓按键命令库教程(紫猫版续)
- 视频编码中的PAFF和MBAFF的区别
- WZ安卓面试宝典App
- MySQL业务账号需要哪些权限_MySQL 日常运维业务账号权限的控制
- Pandas:利用Styler对象设置Series、Dataframe在Jupyter Notebook中的输出样式(1)——基础接口
- java物流管理系统_基于java的物流管理系统
- 学生信息管理系统V2.0
- 关于nomogram核心函数的time.inc函数的设定
- 2018/8/22部分算法总结 二维几何常用算法
- 用IMAP4访问Exchange邮箱
- Siamese Network (应用篇5) :孪生网络用于跟踪 CVPR2016