delphi中formatFloat代码初探(在qt下实现floatformat的函数)

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

整体流程是:

1)解析format格式化字符串

[delphi] view plain copy

  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的结构体中。

[delphi] view plain copy

  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++的实现代码如下:

[cpp] view plain copy

  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. }

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

[delphi] view plain copy

  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的进行格式化处理 。

[delphi] view plain copy

  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

时间: 2024-10-26 00:22:54

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

Delphi中怎样将字符串按给定字符分隔(类似split函数的功能)

Delphi中怎样将字符串按给定字符分隔(类似split函数的功能) 分类:            Delphi2007-05-16 11:094911人阅读评论(2)收藏举报 delphiintegerstringbutton文本编辑function 今天偶尔要做的Delphi程序,其中涉及到了字符串处理,里面有一个功能类似于VB里的split()函数的功能,于是查了很久才查到些资料,现将这些资料整理一下,方便大家. 首先是一个网友自己编的函数.实现了和split()函数的功能. unit U

Delphi中使代码简洁的 5 条忠告(转)

写代码是一种艺术.使用Delphi,任何人都可以轻而易举地开发出某种软件.完成某些任务.而完美的代码则只有真正的高手才能写出.除了正确的缩进.大小写.命名规则之外,请时刻牢记爱因斯坦的名言--简单就是美.下面将谈及的五个代码问题,可能是初学者.甚至一些老鸟都会犯的错误. 忠告一 布尔型变量的赋值操作应该是直接的.例如,在一个if/then/else语句中,if子句将布尔型变量赋值为True,而else子句将其赋为False.下面这段代码的写法是不好的: if If_Love_Delphi the

delphi 中一种好用的数组定义方法以及函数嵌套的使用源代码

type TByteBuff;= array of integer; function abc(a:integer):TByteBuff;; var tempArr:TByteBuff; begin setlength(tempArr,2); tempArr[0] := a; tempArr[1] := a + 10; result:=tempArr; end; procedure TForm1.Button1Click(Sender: TObject); var a : integer; be

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

源:Delphi 中Format的字符串格式化使用说明(转) 一.Format函数的用法 Format是一个很常用,却又似乎很烦的方法,本人试图对这个方法的帮助进行一些翻译,让它有一个完整的概貌,以供大家查询之用: 首先看它的声明: function Format(const Format: string; const Args: array of const): string; overload; 事实上Format方法有两个种形式,另外一种是三个参数的,主要区别在于它是线程安全的,但并不多用

qt 下tablewidget 中要单独使一列不能编辑怎么办?

qt 下tablewidget 中要单独使一列不能编辑怎么办???最好能用一个button 控件控制 2012-03-31 19:57南山杨木 | 分类:其他编程语言 | 浏览2658次 分享到: 2012-04-01 16:29 提问者采纳 热心网友 修改该列item的flags. 例如: #include <QApplication>#include <QTableWidget>#include <QTableWidgetItem>int main(int argc

初探Delphi中的插件编程

前言 我写Delphi程序是从MIS系统入门的,开始尝试子系统划分的时候采用的是MDI窗体的结构.随着系统功能的扩充,不断有新的子系统加入系统中,单个工程会变得非常大,每次做一点修改都要重新编译,单个工程的形式也不利于团队协作.为了提高工作效率,我希望利用DLL动态链接库的形式实现插件结构的编程. 插件结构的编程需要一个插件容器来控制各DLL的运行情况,将划分好的每个子系统安排到一个DLL库文件中.对每个DLL程序需要为容器预留接口函数,一般接口函数包括:启动调用DLL库的函数.关闭DLL库的函

在delphi中执行javascript代码

http://lhdeyx.blog.163.com/blog/static/318196972011101132922916/ 在delphi中执行javascript代码 2011-11-11 15:32:54|  分类: delphi|举报|字号 订阅 下载LOFTER我的照片书  | 有时做项目难免用到代码交叉调用,delphi中执行js就是一种,两种方法可用:一.使用webbrower,比较麻烦二.使用ScriptControl,简单方便:1.首先uses ComObj;2.通用函数:

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

在VC编程中,用SetTimer可以定义一个定时器,到时间了,就响应OnTimer消息,但这种定时器精度太低了.如果需要精度更高一些的定时器(精 确到1ms),可以使用下面的高精度多媒体定时器进行代码优化,可以达到毫秒级的精度,而且使用方便.先要包含头文件"mmsystem.h"和库文 件"winmm.lib". 虽然Win95下可视化开发工具如VC.Delphi.C++   Builder等都有专用的定时器控件Timer,而且使用很方便,可以实现一定的定时功能,但

Delphi中的TChart使用用法

1.TChart Hello world 放一个控件到窗体上,然后写代码加入一个折线数据序列: var Series: TLineSeries; begin Series := TLineSeries.Create(Chart1); Series.Add(100, '头部', clRed); Series.Add(200, '颈部', clGreen); Chart1.AddSeries(Series); end; 这样就会生成一个简单的折线图表,要生成其它类型的数据图表,可以添加不同的数据序列