这2天程序出问题, 用户结算金额经常莫名其妙的多出了小数点后几位, 不用思考 肯定是因为浮点精度不准确的问题

查了一下, 程序中的数据类型使用的是Currency, 按照数据类型的描述, 这个金额类型应该是以实数形式存储的, 完全不会出现精度不准确的问题, 那为什么现实中还是会有莫名其妙的小数出现呢

继续跟踪程序, 发现数据在中转过程中使用了内存表控件, 而金额数据对应的字段类型正好是TCurrencyFiled

写点测试代码, 发现每次从内存表字段存取数据, 就会出现数值误差, 难道是这个字段有问题?

跟踪进源码, 发现TCurrencyFiled是从TDoubleField字段上继承下来的, 莫非这个字段使用的是Double格式数据存储??!!

看一下Help, 然后悲剧的发现, 人家早就告诉你了:

TCurrencyField encapsulates the fundamental behavior common to currency fields. TCurrencyField differs from its immediate ancestor TFloatField only in having a DataType of ftCurrency, and in formatting the value using a currency format (one that represents monetary values) by default. Currency fields can hold values in the range from (positive or negative) 5.0 * 10^-324 to 1.7 * 10^308 with an accuracy of 15 digits. 

Do not confuse TCurrencyField with the Currency data type. Currency fields use the double data type to store and manipulate their values. This data type is the format used by the physical database tables for currency fields. The TBCDField class uses the Currency data type to store and manipulate its value.

If you use the Fields editor at design time to create a persistent field component for the currency field, you can access it by name at runtime. When using dynamic field components, you can access the TCurrencyField instance using the dataset?
s Fields property or FieldByName method.

我嘞个擦.....Currency数据类型对应的居然不是TCurrencyField, 而应该是TBCDField......坑爹啊

最后补充一下: 一般我们常见的基本数据类型就不说了, 基本分为整型和浮点型, 其中整型是实数存储, 每个数据位都代表确切的数, 而浮点则是用指数存储, 表示成什么数完全取决于你要求的精度

所以...实数存储可以直接比较相等, 而指数一般无法比较(不是绝对不能比较)

这里最为特殊的, 就应该属于Currency类型了, 从数据表示上划分, 应该属于浮点类型数据, 因为他有小数, 而从存储形式上来看, 它又属于实数存储, 因为它的每个数据位都代表确切的值

如果还不明白, 可以使用下面的代码测试下:

var
i64: Int64;
c: Currency;
begin
i64 := ;
c := / ;
Move(c, i64, Sizeof(c));
ShowMessage(CurrToStr(c) + ## + IntToStr(i64));
end;

显示的结果是:

17.5714

175714

明白了吧, Currency实际上数据的存储和Int64是一样的, 只不过在使用的时候, 把最后4位认为是小数位而已

关于Currency类型和 TCurrencyFiled的悲剧的更多相关文章

  1. DATETIME类型和BIGINT 类型互相转换

    项目中使用BIGINT来存放时间,以下代码用来转换时间类型和BIGINT类型 SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO -- ========= ...

  2. AngularJs:String类型和JSON相互转换

    最近一周做了一个页面,制作的过程中遇到各种问题,从中可以看出本人的js基础还不够扎实,angularjs也只是刚入门的水平,现在将制作过程中遇到的问题一一汇总,方便以后查阅. 一.String类型和J ...

  3. Timestame类型和String 类型的转化

    Timestame类型和String 类型的转化 String转化为Timestamp: SimpleDateFormat df = new SimpleDateFormat("yyyy-M ...

  4. Python3.x中bytes类型和str类型深入分析

    Python 3最重要的新特性之一是对字符串和二进制数据流做了明确的区分.文本总是Unicode,由str类型表示,二进制数据则由bytes类型表示.Python 3不会以任意隐式的方式混用str和b ...

  5. Date类型和Long类型的相互转换

    Date类型和Long类型的相互转换: import java.text.SimpleDateFormat; import java.util.Date; public class T { publi ...

  6. Java数据类型和MySql数据类型对应一览

    类型名称 显示长度 数据库类型 JAVA类型 JDBC类型索引(int) 描述             VARCHAR L+N VARCHAR java.lang.String 12   CHAR N ...

  7. java中XMLGregorianCalendar类型和Date类型之间的相互转换

    import java.text.SimpleDateFormat;import java.util.Date;import java.util.GregorianCalendar;import ja ...

  8. Java中int类型和tyte[]之间转换及byte[]合并

    JAVA基于位移的 int类型和tyte[]之间转换 [java] view plaincopy /** * 基于位移的int转化成byte[] * @param int number * @retu ...

  9. 数据类型和typeof操作符

    虽然学习js有一段时间了,但是对js的基础语法却是有些生疏.最近在看jquery源码,决定随带总结一些基础的语法知识.今天总结一下数据类型和typeof,这在写js的时候,是不得不知道的知识. 数据类 ...

随机推荐

  1. Android内存进程管理机制

    参考文章: http://www.apkbus.com/android-104940-1-1.htmlhttp://blog.sina.com.cn/s/blog_3e3fcadd0100yjo2.h ...

  2. DOM基础2

    插入元素 <!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF- ...

  3. java unicode转中文

    public static String unicodeToString(String str) { Pattern pattern = Pattern.compile("(\\\\u(\\ ...

  4. BZOJ3553 : [Shoi2014]三叉神经树

    设val[i]为i连出去的树突中输出值为0的个数 如果val[x]<=1,输出值为1,否则输出值为0 修改x就相当于val[f[i]]++或者val[f[i]]-- 用Link-cut Tree ...

  5. hdu 1097 A hard puzzle

    Problem Description lcy gives a hard puzzle to feng5166,lwg,JGShining and Ignatius: gave a and b,how ...

  6. 20145308刘昊阳 《Java程序设计》第7周学习总结

    20145308刘昊阳 <Java程序设计>第7周学习总结 教材学习内容总结 第13章 时间与日期 13.1 认识时间与日期 13.1.1 时间的度量 格林威治时间(GMT) 世界时(UT ...

  7. TYVJ P3522 &&洛谷 P1135 奇怪的电梯 Label:bfs

    题目描述 呵呵,有一天我做了一个梦,梦见了一种很奇怪的电梯.大楼的每一层楼都可以停电梯,而且第i层楼(1<=i<=N)上有一个数字Ki(0<=Ki<=N).电梯只有四个按钮:开 ...

  8. 【BZOJ】2876: [Noi2012]骑行川藏

    题意 给出\(s_i, k_i, v_i', E\),满足\(\sum_{i=1}^{n} k_i s_i ( v_i - v_i' )^2 \le E, v_i > v_i'\),最小化$ \ ...

  9. java.io.IOException: Could not locate executable null\bin\winutils.exe in the Hadoop binaries

    在已经搭建好的集群环境Centos6.6+Hadoop2.7+Hbase0.98+Spark1.3.1下,在Win7系统Intellij开发工具中调试Spark读取Hbase.运行直接报错: ? 1 ...

  10. Photoshop教您快速的制作标准一寸证件照教程

    Photoshop教您快速的制作标准一寸证件照教程 对急需证件照的朋友,只要有一部相机,有电脑安装了PS软件,就可很快自己完成一寸照片的制作. 首先将相机卡里的照片存放在电脑硬盘里: 打开PS图片处理 ...