I have some code that gets the leading value (non-zero) of a Double using normal math instead of String Math...
For Example:
0.020 would return 2 3.12 would return 3 1000 should return 1The code I hav开发者_开发知识库e at the moment is:
LeadingValue := Trunc(ResultValue * Power(10, -(Floor(Log10(ResultValue)))))
However when ResultValue is 1000 then LeadingValue ends up as 0.
What can I do to fix this problem I'm assuming is being caused by floating point errors?
Thanks.
I'm curious as to why you can't / won't use String manipulation for this. Could you explain further?
The most obvious thing you can do to fix the problem is to convert the number to a String and find the first non zero digit.
A possible way to cheat around the rounding problems:
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.
if you divide instead of multiply, it fixes your test cases. Overall, it will yield better result as the "Power" result won't have a fractional value. I'm afraid it might not have a 100% case coverage, but unless a better solution is proposed, this should be better than what you have.
function Func(Value : Double) : Integer;
begin
Result := Trunc(Value / Power(10, (Floor(Log10(Value)))))
end;
You're not going to be able to do this with 100% accuracy using floating-point math. What you need to do essentially is to convert a binary floating-point value to a decimal string. Routines that do that accurately, like David Gay's dtoa.c, use high precision (integer) arithmetic.
精彩评论