12

Java version 1.7.0_09 のソースコードを読んだところ、Integer クラスの toString メソッドの実現で負の int を使用して mod 演算を計算していることがわかりましたが、意味はありますか? コードは次のとおりです。

public static String toString(int i, int radix) {

    if (radix < Character.MIN_RADIX || radix > Character.MAX_RADIX)
        radix = 10;

    /* Use the faster version */
    if (radix == 10) {
        return toString(i);
    }

    char buf[] = new char[33];
    boolean negative = (i < 0);
    int charPos = 32;

    if (!negative) {     
        i = -i;                //***** change i to negative
    }

    while (i <= -radix) {
        buf[charPos--] = digits[-(i % radix)];   //***** change back to positive after 
                                                 //***** mod operation
        i = i / radix;
    }
    buf[charPos] = digits[-i];

    if (negative) {
        buf[--charPos] = '-';
    }

    return new String(buf, charPos, (33 - charPos));
}
4

1 に答える 1

13

< radixアルゴリズムによると、文字バッファーを右から左に数字で埋める小さな ( ) 非負整数のストリームが必要です。これを機能させるための標準的な小学校の方法は、数値の先頭に記号を付けてから、数値の絶対値を出力することです。

iしかし、ルールがそのループで常に正である場合を想像してみてください。

if (negative) {
    i = -i; // change i to positive
}

である場合iInteger.MIN_VALUE-iまた であるInteger.MIN_VALUE2 の補数の整数変数は、正の整数よりも負の整数を 1 つ多く格納できます。ただし、不変式が代わりにi常にの絶対値である場合、常にint.

Math.abs()またはifブロックを使用しないのはなぜですか?toString当然のことながら、整数は多くのコンピュータ プログラムで非常に頻繁に文字列に変換されるため、できるだけ高速に保つことが役立ちます。Math.abs()問題は、マシン コードにコンパイルするときに、ステートメントとステートメントの両方がif分岐命令を使用するようにコンパイルされる可能性が高いことです。分岐は、命令のパイプライン処理に干渉する傾向があります。したがって、パフォーマンスに注意を払うifときは、可能であればループからステートメントを削除することを選択できます。

注: この種の最適化は、めったに良い考えではありません! コードが非常に頻繁に呼び出される (このコードのように) か、多くのユーザーと少数のリーダー/修飾子 (このコードのように) でライブラリを構築していない限り、パフォーマンスの向上はごくわずかであり、コードが読みにくく、理解しにくくなり、変化する。この最適化を行うことで、Java エンジニアはあなたのコードをわずかに高速化するかもしれませんが、あなたが書いたコードにこのような手法を組み込むと、同僚や採点者はスタック オーバーフローに、なぜあなたのコードが理解しにくいのか尋ねようとしないかもしれません。:)

TL;DR: 経験に基づいた推測ですが、これは 2 の補数演算とコードの最適化を組み合わせたものです。

于 2012-10-26T05:08:06.470 に答える