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

时间:2022-06-12 00:14:33

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

整体流程是:

1)解析format格式化字符串

[delphi]  

 

 

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

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

Result := 0;  

 DecimalSep := AFormatSettings.DecimalSeparator;  

//根据系统取得小数点的符号  

 ThousandsSep := AFormatSettings.ThousandSeparator;  

//根据系统取得千分位的符号。这两个最好也通过系统API来取,如果要做国际化的话,这两个在不同的系统上是不一样的。  

 if ValueType = fvCurrency then  

   Temp := Currency(Value)  

 else  

   Temp := Extended(Value);  

 if Extended(Temp) > then  

   AIndex := 0  

 else  

   if Extended(Temp) < then  

     AIndex := 1  

   else  

     AIndex := 2;  

 SectionIndex := FindSection(AIndex);  

 Section := ScanSection(SectionIndex);  //这个主要是取得format的格式字符串,取得小数点,千分位的位置,还有是否显示科学计数法,取得填充0的位置。  

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

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

由于Delphi中的extended的类型是10字节的,C++没有对应数据类型,而且它的内存结构比较复杂。这个函数就自己实现了。它的功能就是把float的类型数据存入到TFloatRec的结构体中。

[delphi]  

 

 

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

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

  TFloatRec = packed record  

    Exponent: Smallint;  

  //表示几位整数(100,对应的3)  

    Negative: Boolean;  

 //表示是否为负数  

    Digits: array[0..20] of AnsiChar;  

//将浮点数中的数字取出来存到里面,如果是0.XXX的,第一个0不存。  

  end;  

C++的实现代码如下:

[cpp]  

 

 

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

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

result->negative = value < 0;  

  

if (fabs(value) < 1e-16)  

{  

    result->exponent = 0;  

    result->digits[0] = ‘\0‘;  

    return;  

}  

  

if (result->negative)  

{  

    value = abs(value);  

}  

  

GString strDigits = GString::number(value, ‘f‘, 18);  

result->exponent = strDigits.indexOf("."); //算出小数点前的位数  

int nStrIndex = 0;  

if (value < 1) //小数前的那个0不算  

{  

    result->exponent = 0;  

    nStrIndex = 1;  

}  

int nIndex = 0;  

while (true) //把数字压入floatRec中  

{  

    if (strDigits[nStrIndex] == QChar(‘.‘))  

    {  

        nStrIndex++;  

        continue;  

    }  

    if (nStrIndex > 19 || (nStrIndex >= strDigits.length()))  

    {  

        break;  

    }  

    result->digits[nIndex] = strDigits[nStrIndex].toLatin1();  

    nStrIndex++;  

    nIndex++;  

}  

  

if (result->exponent + decimals < 0)  

{  

    result->exponent = 0;  

    result->negative = false;  

    result->digits[0] = 0;  

    return;  

}  

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

[delphi]