修复浮点错误

时间:2010-05-30 23:19:28

标签: delphi floating-accuracy

我有一些代码使用普通数学而不是字符串数学得到Double的前导值(非零)...

例如:
0.020将返回2
3.12将返回3
1000 应该返回1

我目前的代码是:

LeadingValue := Trunc(ResultValue * Power(10, -(Floor(Log10(ResultValue)))))

但是当ResultValue为1000时,则LeadingValue最终为0。

我可以做些什么来解决这个问题我假设是由浮点错误引起的?

感谢。

4 个答案:

答案 0 :(得分:1)

我很好奇为什么你不能/不会为此使用字符串操作。你能进一步解释一下吗?

解决问题最明显的方法是将数字转换为字符串并找到第一个非零数字。

答案 1 :(得分:1)

欺骗四舍五入问题的可能方法:

program Project1;

{$APPTYPE CONSOLE}

uses
  SysUtils,
  Math;

function LeadingValue(num: extended): integer;
const
  ExtendedResolution = 1E-19 * 1000; // from Math
begin
  num := Abs(num);
  Result := Trunc(num * Power(10, -(Floor(Log10(num)))) + ExtendedResolution);
end;

begin
  try
    Writeln(LeadingValue(0.02));
    Writeln(LeadingValue(3.12));
    Writeln(LeadingValue(1000));
    Writeln(LeadingValue(0.9999999999));
    Writeln(LeadingValue(1.0000000001));
    Writeln(LeadingValue(-0.02));
    Writeln(LeadingValue(-3.12));
    Writeln(LeadingValue(-1000));
    Writeln(LeadingValue(-0.9999999999));
    Writeln(LeadingValue(-1.0000000001));
    Readln;
  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;
end.

答案 2 :(得分:0)

如果你分而不是乘法,它会修复你的测试用例。总的来说,它会产生更好的结果,因为“Power”结果不会有小数值。我担心它可能没有100%的案例覆盖率,但除非提出更好的解决方案,否则这应该比你拥有的更好。

function Func(Value : Double) : Integer;
begin
  Result := Trunc(Value / Power(10, (Floor(Log10(Value)))))
end;

答案 3 :(得分:0)

使用浮点数学,你无法以100%的准确率完成这项工作。你需要做的就是将二进制浮点值转换为十进制字符串。准确执行此操作的例程(如 David Gay's dtoa.c)使用高精度(整数)算法。