由于项目需要,需要在qt下实现floatformat的函数。之前写过一个,但是写得不好。决定重新写一个,参考delphi xe2下的实现。把xe2下的相关代码都看了一遍,xe2的代码思路在这里贴出来。xe2下的代码在system.sysutils下,核心函数是InternalFloatToTextFmt。它有汇编的版本跟纯pascal的版本。汇编看不懂,参考的是纯pascal的版本。

整体流程是:

1)解析format格式化字符串

  1. Result := 0;
  2. DecimalSep := AFormatSettings.DecimalSeparator;
  3. //根据系统取得小数点的符号
  4. ThousandsSep := AFormatSettings.ThousandSeparator;
  5. //根据系统取得千分位的符号。这两个最好也通过系统API来取,如果要做国际化的话,这两个在不同的系统上是不一样的。
  6. if ValueType = fvCurrency then
  7. Temp := Currency(Value)
  8. else
  9. Temp := Extended(Value);
  10. if Extended(Temp) > 0 then
  11. AIndex := 0
  12. else
  13. if Extended(Temp) < 0 then
  14. AIndex := 1
  15. else
  16. AIndex := 2;
  17. SectionIndex := FindSection(AIndex);
  18. Section := ScanSection(SectionIndex);  //这个主要是取得format的格式字符串,取得小数点,千分位的位置,还有是否显示科学计数法,取得填充0的位置。

这段代码主要是分析格式化字符串。这个可以直接参考代码翻译成C++的。

2)将浮点数转成十进制的数字,用的函数是 FloatToDecimal(FloatValue, Value, ValueType, Precision, Digits);

由于Delphi中的extended的类型是10字节的,C++没有对应数据类型,而且它的内存结构比较复杂。这个函数就自己实现了。它的功能就是把float的类型数据存入到TFloatRec的结构体中。
  1. TFloatRec = packed record
  2. Exponent: Smallint;
  3. //表示几位整数(100,对应的3)
  4. Negative: Boolean;
  5. //表示是否为负数
  6. Digits: array[0..20] of AnsiChar;
  7. //将浮点数中的数字取出来存到里面,如果是0.XXX的,第一个0不存。
  8. end;

C++的实现代码如下:

  1. result->negative = value < 0;
  2. if (fabs(value) < 1e-16)
  3. {
  4. result->exponent = 0;
  5. result->digits[0] = '\0';
  6. return;
  7. }
  8. if (result->negative)
  9. {
  10. value = abs(value);
  11. }
  12. GString strDigits = GString::number(value, 'f', 18);
  13. result->exponent = strDigits.indexOf("."); //算出小数点前的位数
  14. int nStrIndex = 0;
  15. if (value < 1) //小数前的那个0不算
  16. {
  17. result->exponent = 0;
  18. nStrIndex = 1;
  19. }
  20. int nIndex = 0;
  21. while (true) //把数字压入floatRec中
  22. {
  23. if (strDigits[nStrIndex] == QChar('.'))
  24. {
  25. nStrIndex++;
  26. continue;
  27. }
  28. if (nStrIndex > 19 || (nStrIndex >= strDigits.length()))
  29. {
  30. break;
  31. }
  32. result->digits[nIndex] = strDigits[nStrIndex].toLatin1();
  33. nStrIndex++;
  34. nIndex++;
  35. }
  36. if (result->exponent + decimals < 0)
  37. {
  38. result->exponent = 0;
  39. result->negative = false;
  40. result->digits[0] = 0;
  41. return;
  42. }

这段代码执行后,会根据小数位数进行截断,还有进行四舍五入。

  1. while true do
  2. begin
  3. Result.Digits[J] := #0;
  4. Dec(J);
  5. if J < 0 then
  6. begin
  7. Result.Digits[0] := '1';
  8. Inc(Result.Exponent);
  9. Exit;
  10. end;
  11. Inc(Result.Digits[J]);
  12. if Result.Digits[J] <= '9' then
  13. Exit;
  14. end;
3)对之前处理的TFloatRec的进行格式化处理 。
  1. if (FormatLength = 0) or (GetCharIndex(Format, 0) = ';') or
  2. ((FloatValue.Exponent >= 18) and (not Scientific)) or
  3. (FloatValue.Exponent = $7FF) or (FloatValue.Exponent = $800) then
  4. if Unicode then
  5. Result := FloatToText(PWideChar(Buf), Value, ValueType, ffGeneral, 15, 0)
  6. else
  7. Result := FloatToText(PAnsiChar(Buf), Value, ValueType, ffGeneral, 15, 0)
  8. 这个可以直接调QSTring::num()来实现,将浮点数转成字符串
  9. else
  10. ApplyFormat;//这个函数来实现格式化,可以直接翻译成C++
applyFormat的函数主要是根据那个格式化字符串,取出TFloatRec的digits里的数字拼成一个字符串出来。
 
整体来说思路就是这样。

http://blog.csdn.net/hpjx1987/article/details/25462807

delphi中formatFloat代码初探(在qt下实现floatformat的函数)的更多相关文章

  1. 在Delphi中使用ShellExecute(handle, 'open', PChar(fname),nil, nil, SW_HIDE)函数应注意的问题

    在Delphi中使用ShellExecute(handle, 'open', PChar(fname),nil, nil, SW_HIDE)函数应注意的问题: 一.对一般vcl程序及isapi dll ...

  2. python调用另一个文件中的代码,pycharm环境下:同文件夹下文件(.py)之间的调用,出现红线问题

    如何调用另一个python文件中的代码无论我们选择用何种语言进行程序设计时,都不可能只有一个文件(除了“hello world”),通常情况下,我们都需要在一个文件中调用另外一个文件的函数呀数据等等, ...

  3. Delphi 中Format的字符串格式化使用说明(转)

    源:Delphi 中Format的字符串格式化使用说明(转) 一.Format函数的用法 Format是一个很常用,却又似乎很烦的方法,本人试图对这个方法的帮助进行一些翻译,让它有一个完整的概貌,以供 ...

  4. Python中生成器和迭代器的区别(代码在Python3.5下测试):

    https://blog.csdn.net/u014745194/article/details/70176117 Python中生成器和迭代器的区别(代码在Python3.5下测试):Num01–& ...

  5. Delphi中Form的position属性与代码自定义窗体位置

    通过Form的Position属性可设置窗体的初始位置,如选择DesktopCenter为桌面中心,ScreenCenter为屏幕中心,等等. 这个属性在很多时候简化了程序代码. 但是,如果设置了po ...

  6. 初探Delphi中的插件编程

    前言 我写Delphi程序是从MIS系统入门的,开始尝试子系统划分的时候采用的是MDI窗体的结构.随着系统功能的扩充,不断有新的子系统加入系统中,单个工程会变得非常大,每次做一点修改都要重新编译,单个 ...

  7. 在delphi中执行javascript代码

    有时做项目难免用到代码交叉调用,delphi中执行js就是一种,两种方法可用: 一.使用webbrower,比较麻烦 二.使用ScriptControl,简单方便: 1.首先 uses ComObj; ...

  8. 在Delphi中高效执行JS代码

    因为一些原因,需要进行encodeURIComponent和decodeURIComponent编码,在Delphi中找了一个,首先是发现不能正确编码+号,后面强制处理替换了,勉强可用. 后面发现多次 ...

  9. VC++或QT下 高精度 多媒体定时器

    在VC编程中,用SetTimer可以定义一个定时器,到时间了,就响应OnTimer消息,但这种定时器精度太低了.如果需要精度更高一些的定时器(精 确到1ms),可以使用下面的高精度多媒体定时器进行代码 ...

随机推荐

  1. Beyond Compare 相同文件对比结果仍显示红色 解决方案

    转载:http://blog.sina.com.cn/s/blog_4d4bc1110100zj7x.html   1. 问题详细描述如下. 下图显示对比结果中,两侧的aaa.xml是一模一样,会话中 ...

  2. 缓存(之一) 使用Apache Httpd实现http缓存

    http://www.tuicool.com/articles/EFfeu2 HTTP性能的问题与方案 一个最终用户访问一个网页,从浏览器发出请求,到接受请求,时间大体上消耗在了以下几个部分: 建立t ...

  3. ASP.NET 5 初识

    ASP.NET 5 是一个跨平台的全新框架,不再依赖IIS.下面介绍一下简单的Hello World 例子. 1. 安装kvm 用管理员权限打开cmd .如下图: 执行如下的脚本: @powershe ...

  4. Java编程思想读书笔记--第14章类型信息

    7.动态代理 代理是基本的设计模式之一,它是你为了提供额外的或不同的操作,而插入的用来代替“实际”对象的对象.这些操作通常涉及与“实际”对象的通信,因此代理通常充当着中间人的角色. 什么是代理模式? ...

  5. Yii 通过widget小物件生成添加表单

    通过widget小物件创建添加商品的表单 视图里,表单以endWidget();?>结束 最终效果: 把表单提交过来的信息保存到数据库中去. 补充要点: 密码表单: <?php echo ...

  6. VS2013中Django流水账笔记--配置环境

    一.开发环境 Win7 64位搭建开发环境.需要准备VS2013.Python34.PTVS2013. 1.http://pytools.codeplex.com/ 下载工具,下载之后进行安装即可,我 ...

  7. C#方法解析

    “方法”是包含一系列语句的代码块. 程序通过“调用”方法并指定所需的任何方法参数来执行语句. 在 C# 中,每个执行指令 都是在方法的上下文中执行的. 最近在写一个反射调用时,需要通过反射来调用方法. ...

  8. 、Dll文件的编写 调用 说明

    1>新建Dll文件TestLib.dll 新建Unit文件U_TestFunc U_TestFunc代码如下: unit U_TestFunc; interface uses //尽可能的少us ...

  9. 用twisted 做一个日志收集系统

    混沌初开 起初我是不会上logging模块的,直接导致了即时有了日志,我也存到了数据库中,而且量也不大,是否能遇到异常只能靠运气了 开天辟地 不得不说,没有任何输出的线上环境真的挺难调试的,当然,聪明 ...

  10. configure: error: zlib library and headers are required

    configure: error: zlib library and headers are required (1)直接看是zlib没安装导致的,yum list |grep zlib* 看到的是全 ...