6

数値を文字列にキャストしてからlen()を使用して桁数を決定しているコードに出くわしました。

Function numOfDigits_len(n As Long) As Long
    numOfDigits_len = Len(Str(n)) - 1
End Function

これは機能しますが、文字列を使用しないメソッドに比べて遅いことがわかっていたので、log() を使用するメソッドを作成しました。

Function numOfDigits_log(n As Long) As Long
    numOfDigits_log = Int(Log(n) / Log(10)) + 1
End Function

実行時間を 1/2 短縮できたのは良かったのですが、特定のケースで奇妙なことが起こっていました。

  n     numOfDigits_log(n)
=====  ====================
 999            3
1000            3
1001            4

1000適切に処理されません。浮動小数点と丸めの問題が原因だと思いました。

Function numOfDigits_loop(ByVal n As Long) As Long
    Do Until n = 0
        n = n \ 10
        numOfDigits_loop = numOfDigits_loop + 1
    Loop
End Function

これを書いたところ、数値が 10^6 を超えると最大 10% 遅くなり、n が大きくなるにつれてゆっくりと大きくなるようです。私が実用的であればそれは問題ありませんが、もっと理想的なものを見つけたいと思います.

私の質問は、 log() メソッドを正確に使用する方法があるかどうかです。私は次のようなことができます

Function numOfDigits_log(n As Long) As Long
    numOfDigits_log = Int(Log(n) / Log(10) + 0.000000001) + 1
End Function

しかし、それは非常に「ハック」のようです。log() メソッドよりも高速または同程度の高速な方法はありますか? 注: この種の最適化は多くの場合無意味だと認識していますが、これに遭遇したので「修正」したいと思います。

4

3 に答える 3

1

以前にも回答したことがありますが、見つけられなかったので、基本は次のとおりです。

int i = ... some number >= 0 ...
int n = 1;
if (i >= 100000000){i /= 100000000; n += 8;}
if (i >= 10000){i /= 10000; n += 4;}
if (i >= 100){i /= 100; n += 2;}
if (i >= 10){i /= 10; n += 1;}

それはCですが、あなたはその考えを理解します。

于 2013-06-19T20:56:17.103 に答える
1

while ループは正確性を保証します。つまり、浮動小数点計算を使用しません。

int numDigits = 0;
while(num != 0) {
    num /= 10;
    numDigits++;
}

より大きな除数を使用してこれを高速化することもできます

int numDigits = 0;
if(num >= 100000 || num <= -100000) {
    int prevNum;
    while(num != 0) {
        prevNum = num;
        num /= 100000;
        numDigits += 5;
    }
    num = prevNum;
    numDigits -= 5;
}
while(num != 0) {
    num /= 10;
    numDigits++;
}
于 2013-06-19T20:30:19.303 に答える
0

あなたはこれを気に入るはずです。

私たちは10進法のシステムに住んでいます!つまり、ROUND UP を実行するだけです。

ある数値の長さ ALWAYS = ceiling (log n). たとえば、7456412 (7 桁の数字) です。ログ (7456412) = 6.8...切り上げると 7 になります。ログ (9999) = 3.9999。切り上げて 4 です。

特殊なケースは、丸める必要がない場合、または 10 の累乗がある場合です。たとえば、log(1000) = 3. 10 の累乗を検出できる場合は、ログ結果に 1 を追加します。そしてあなたは勝ちます!

この検出を行う方法は次のようなものです

double log10;
int clog10;
int length;

log10 = (Log(n) / Log(10)); // can also use a private static final long hardcoded for Log(10)
clog10 = ceiling(log10);
if (Int(log10) == clog10)
  length = clog10 + 1;
else
  length = clog10;
于 2013-06-19T20:25:44.620 に答える