zoukankan      html  css  js  c++  java
  • delphi中formatFloat代码初探(在qt下实现floatformat的函数)

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

      整体流程是:

    1)解析format格式化字符串

    [delphi] view plain copy
     
     在CODE上查看代码片派生到我的代码片
    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) > then  
    11.    AIndex := 0  
    12.  else  
    13.    if Extended(Temp) < 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
     
     在CODE上查看代码片派生到我的代码片
    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
     
     在CODE上查看代码片派生到我的代码片
    1. result->negative = value < 0;  
    2.   
    3. if (fabs(value) < 1e-16)  
    4. {  
    5.     result->exponent = 0;  
    6.     result->digits[0] = '';  
    7.     return;  
    8. }  
    9.   
    10. if (result->negative)  
    11. {  
    12.     value = abs(value);  
    13. }  
    14.   
    15. GString strDigits = GString::number(value, 'f', 18);  
    16. result->exponent = strDigits.indexOf("."); //算出小数点前的位数  
    17. int nStrIndex = 0;  
    18. if (value < 1) //小数前的那个0不算  
    19. {  
    20.     result->exponent = 0;  
    21.     nStrIndex = 1;  
    22. }  
    23. int nIndex = 0;  
    24. while (true) //把数字压入floatRec中  
    25. {  
    26.     if (strDigits[nStrIndex] == QChar('.'))  
    27.     {  
    28.         nStrIndex++;  
    29.         continue;  
    30.     }  
    31.     if (nStrIndex > 19 || (nStrIndex >= strDigits.length()))  
    32.     {  
    33.         break;  
    34.     }  
    35.     result->digits[nIndex] = strDigits[nStrIndex].toLatin1();  
    36.     nStrIndex++;  
    37.     nIndex++;  
    38. }  
    39.   
    40. if (result->exponent + decimals < 0)  
    41. {  
    42.     result->exponent = 0;  
    43.     result->negative = false;  
    44.     result->digits[0] = 0;  
    45.     return;  
    46. }  

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

    [delphi] view plain copy
     
     在CODE上查看代码片派生到我的代码片
    1. while true do  
    2.     begin  
    3.       Result.Digits[J] := #0;  
    4.       Dec(J);  
    5.       if J < then  
    6.       begin  
    7.         Result.Digits[0] := '1';  
    8.         Inc(Result.Exponent);  
    9.         Exit;  
    10.       end;  
    11.   
    12.       Inc(Result.Digits[J]);  
    13.       if Result.Digits[J] <= '9' then  
    14.         Exit;  
    15.     end;  
    3)对之前处理的TFloatRec的进行格式化处理 。
    [delphi] view plain copy
     
     在CODE上查看代码片派生到我的代码片
    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

  • 相关阅读:
    ASP.NET程序中常用的三十三种代码【转】
    BTree,BTree,B+Tree,B*Tree都是什么
    调用Google地图
    JS特效总结
    2005 加入博客园
    .net Windows服务程序安装与安装程序的制作
    七夕,爱似流年
    JS+CSS仿魔兽游戏进入进度条特效
    常用正则表达式
    Google翻译网站添加Google翻译,让老外也看的懂你的网站
  • 原文地址:https://www.cnblogs.com/findumars/p/5947604.html
Copyright © 2011-2022 走看看