2

String Math の代わりに通常の数学を使用して、Double の先頭の値 (ゼロ以外) を取得するコードがいくつかあります...

例:
0.020 は 2 を返します
3.12 は 3 を返します
10001 を返します

私が現時点で持っているコードは次のとおりです。

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

ただし、ResultValue が 1000 の場合、LeadingValue は 0 になります。

浮動小数点エラーが原因だと思われるこの問題を解決するにはどうすればよいですか?

ありがとう。

4

4 に答える 4

1

このために文字列操作を使用できない/使用しない理由について知りたいです。さらに説明してもらえますか?

問題を解決するためにできる最も明白なことは、数値を文字列に変換し、最初のゼロ以外の数字を見つけることです。

于 2010-05-30T23:44:15.833 に答える
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.
于 2010-05-31T06:37:27.653 に答える
0

浮動小数点演算を使用して 100% の精度でこれを行うことはできません。基本的に行う必要があるのは、2 進浮動小数点値を 10 進文字列に変換することです。David Gay の dtoa.c のように、これを正確に行うルーチンは、高精度 (整数) 演算を使用します。

于 2010-06-01T01:10:10.320 に答える
0

乗算ではなく除算すると、テスト ケースが修正されます。全体として、「パワー」の結果は分数値を持たないため、より良い結果が得られます。残念ながら、100% のケースをカバーしていない可能性がありますが、より良い解決策が提案されない限り、これはあなたが持っているものよりも優れているはずです.

function Func(Value : Double) : Integer;
begin
  Result := Trunc(Value / Power(10, (Floor(Log10(Value)))))
end;
于 2010-05-31T17:01:21.477 に答える