这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 自动化测试—robotium(六) 通过命令行执行Robotium自动化测试用例及导出报告

    1.运行测试工程下的所有用例 adb shell am instrument -w com.application.test/android.test.InstrumentationTestRunne ...

  2. WPF Datagrid multiple selecteditems in MVVM

    I can assure you: SelectedItems is indeed bindable as a XAML CommandParameter After a lot of digging ...

  3. dplyr包--数据操作与清洗

    1.简介 在我们数据分析的实际应用中,我们可能会花费大量的时间在数据清洗上,而如果使用 R 里面自带的一些函数(base 包的 transform 等),可能会觉得力不从心,或者不是很人性化.好在我们 ...

  4. data.table包

    data.table 1.生成一个data.table对象 生成一个data.table对象,记为DT. library(data.table) :],V3=round(rnorm(),),V4=:) ...

  5. BZOJ3979 : [WF2012]infiltration

    答案是$O(\log n)$级别的,故答案不超过6. 当答案是12345时,暴力枚举+压位检验即可,否则直接输出6. 时间复杂度$O(n^5)$. #include<cstdio> #de ...

  6. BZOJ4367 : [IOI2014]holiday假期

    设 $fl[i]$表示从$S$向左走,用了不超过$i$天且不回头的最大收益. $fr[i]$表示从$S$向右走,用了不超过$i$天且不回头的最大收益. $gl[i]$表示从$S$向左走,用了不超过$i ...

  7. BZOJ4260 Codechef REBXOR 题解

    题目大意: 有一个长度为n的序列,求1≤l1≤r1<l2≤r2≤n使得(⊕r1i=l1ai)+(⊕r2i=l2ai)最大,输出这个最大值. 思路: 用Trie求出前缀异或和以及后缀异或和,再求出 ...

  8. ajaxFileUpload + lua-resty-upload 上传文件

    ajaxFileUpload下载地址 地址:http://pan.baidu.com/s/1mgJypz6 html页面 <!DOCTYPE HTML PUBLIC "-//W3C// ...

  9. C#面向对象之属性

    1.属性的定义及使用 class MyClass { ; //属性的定义 private string name = ""; //属性的定义 public int Id { get ...

  10. The Unsolvable Problem

    The Unsolvable Problem 题目链接:http://acm.hust.edu.cn/vjudge/problem/visitOriginUrl.action?id=45783 题意: ...