由于项目需要,需要在qt下实现floatformat的函数。之前写过一个,但是写得不好。决定重新写一个,参考delphi xe2下的实现。把xe2下的相关代码都看了一遍,xe2的代码思路在这里贴出来。xe2下的代码在system.sysutils下,核心函数是InternalFloatToTextFmt。它有汇编的版本跟纯pascal的版本。汇编看不懂,参考的是纯pascal的版本。
整体流程是:
1)解析format格式化字符串
- Result := 0;
- DecimalSep := AFormatSettings.DecimalSeparator;
- ThousandsSep := AFormatSettings.ThousandSeparator;
- if ValueType = fvCurrency then
- Temp := Currency(Value)
- else
- Temp := Extended(Value);
- if Extended(Temp) > 0 then
- AIndex := 0
- else
- if Extended(Temp) < 0 then
- AIndex := 1
- else
- AIndex := 2;
- SectionIndex := FindSection(AIndex);
- Section := ScanSection(SectionIndex);
这段代码主要是分析格式化字符串。这个可以直接参考代码翻译成C++的。
2)将浮点数转成十进制的数字,用的函数是 FloatToDecimal(FloatValue, Value, ValueType, Precision, Digits);
由于Delphi中的extended的类型是10字节的,C++没有对应数据类型,而且它的内存结构比较复杂。这个函数就自己实现了。它的功能就是把float的类型数据存入到TFloatRec的结构体中。
- TFloatRec = packed record
- Exponent: Smallint;
-
- Negative: Boolean;
-
- Digits: array[0..20] of AnsiChar;
- end;
C++的实现代码如下:
- 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)
- {
- result->exponent = 0;
- nStrIndex = 1;
- }
- int nIndex = 0;
- while (true)
- {
- 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;
- }
这段代码执行后,会根据小数位数进行截断,还有进行四舍五入。
- while true do
- begin
- Result.Digits[J] := #0;
- Dec(J);
- if J < 0 then
- begin
- Result.Digits[0] := ‘1‘;
- Inc(Result.Exponent);
- Exit;
- end;
-
- Inc(Result.Digits[J]);
- if Result.Digits[J] <= ‘9‘ then
- Exit;
- end;
3)对之前处理的TFloatRec的进行格式化处理 。
- if (FormatLength = 0) or (GetCharIndex(Format, 0) = ‘;‘) or
- ((FloatValue.Exponent >= 18) and (not Scientific)) or
- (FloatValue.Exponent = $7FF) or (FloatValue.Exponent = $800) then
- if Unicode then
- Result := FloatToText(PWideChar(Buf), Value, ValueType, ffGeneral, 15, 0)
- else
- Result := FloatToText(PAnsiChar(Buf), Value, ValueType, ffGeneral, 15, 0)
- 这个可以直接调QSTring::num()来实现,将浮点数转成字符串
- else
- ApplyFormat;
applyFormat的函数主要是根据那个格式化字符串,取出TFloatRec的digits里的数字拼成一个字符串出来。
整体来说思路就是这样。
http://blog.csdn.net/hpjx1987/article/details/25462807
delphi中formatFloat代码初探(在qt下实现floatformat的函数)
原文:http://www.cnblogs.com/findumars/p/5947604.html