web-dev-qa-db-ja.com

Math.abs()を使用せずに数値の絶対値を見つける

JavaでMath.abs()メソッドを使用せずに数値の絶対値を見つける方法はありますか。

19
Theja

Math.absの内部を見ると、おそらく最良の答えを見つけることができます。

例えば、フロートの場合:

    /*
     * Returns the absolute value of a {@code float} value.
     * If the argument is not negative, the argument is returned.
     * If the argument is negative, the negation of the argument is returned.
     * Special cases:
     * <ul><li>If the argument is positive zero or negative zero, the
     * result is positive zero.
     * <li>If the argument is infinite, the result is positive infinity.
     * <li>If the argument is NaN, the result is NaN.</ul>
     * In other words, the result is the same as the value of the expression:
     * <p>{@code Float.intBitsToFloat(0x7fffffff & Float.floatToIntBits(a))}
     *
     * @param   a   the argument whose absolute value is to be determined
     * @return  the absolute value of the argument.
     */
    public static float abs(float a) {
        return (a <= 0.0F) ? 0.0F - a : a;
    }
54
mihaisimi

はい:

_abs_number = (number < 0) ? -number : number;
_

整数の場合、これは正常に動作します(intとして絶対値を表現できない_Integer.MIN_VALUE_を除く)。

浮動小数点数の場合、物事はより微妙です。たとえば、このメソッド(およびこれまでに投稿された他のすべてのメソッド)は、 負のゼロ を正しく処理しません。

自分でそのような微妙な問題に対処する必要を避けるために、私のアドバイスは Math.abs() に固執することです。

19
NPE

このような:

if (number < 0) {
    number *= -1;
}
13
tibtof

Javaは静的に型付けされた言語であるため、intをとるabs-methodは、floatがfloatを返すと予想される場合はintを返し、Doubleの場合はDoubleを返します。ダブルスやダブルスなどの場合は、常にボックス化または非ボックス化型を返すことができます。

したがって、タイプごとに1つのメソッドが必要ですが、新しい問題があります。byte、short、int、longの場合、負の値の範囲は正の値よりも1大きくなります。

したがって、メソッドに対して返されるもの

byte abs (byte in) {
   // @todo
}

ユーザーが-128でabsを呼び出すと?範囲がすべての可能な入力値に適合することが保証されるように、常に次の大きな型を返すことができます。これは長い間、通常の大きな型が存在しない問題を引き起こし、テスト後にユーザーが常に値をキャストするようにします-面倒かもしれません。

2番目のオプションは、算術例外をスローすることです。これにより、X.MIN_VALUEが発生しないなど、入力が制限されていることがわかっている状況でのキャストと戻り型のチェックが防止されます。 intとして表されるMONTHを考えてください。

byte abs (byte in) throws ArithmeticException {
   if (in == Byte.MIN_VALUE) throw new ArithmeticException ("abs called on Byte.MIN_VALUE"); 
   return (in < 0) ? (byte) -in : in; 
}

「MIN_VALUEのまれなケースを無視しましょう」という習慣はオプションではありません。最初にコードを機能させ、次に高速にします。ユーザーがより高速でバグのあるソリューションを必要とする場合は、自分で作成する必要があります。動作する可能性のある最も単純な解決策は、単純ですが、それほど単純ではないということです。

コードは状態に依存しないため、メソッドは静的にすることができ、静的にする必要があります。これにより、簡単なテストが可能になります。

public static void main (String args []) {
    System.out.println (abs(new Byte ( "7")));
    System.out.println (abs(new Byte ("-7")));
    System.out.println (abs((byte)  7));
    System.out.println (abs((byte) -7));
    System.out.println (abs(new Byte ( "127")));
    try
    {
        System.out.println (abs(new Byte ("-128")));
    }
    catch (ArithmeticException ae)
    {
        System.out.println ("Integer: " + Math.abs (new Integer ("-128")));
    }
    System.out.println (abs((byte)  127));
    System.out.println (abs((byte) -128));
}

最初の例外をキャッチし、デモンストレーションのために2番目の例外に実行させます。

プログラミングには悪い習慣があります。つまり、プログラマーは正しいコードよりも高速を重視します。お気の毒に!


なぜ正の値よりも負の値があるのか​​興味があるなら、 diagram for yo があります。

5
user unknown

現代のプロセッサでの分岐の問題は通常問題ではないため、これはボトルネックではありませんが、整数の場合は、ここで概説するように分岐のないソリューションに行くことができます: http:// graphics .stanford.edu /〜seander/bithacks.html#IntegerAbs

(x + (x >> 31)) ^ (x >> 31);

ただし、これはInteger.MIN_VALUEの明らかなケースでは失敗します。したがって、これは独自のリスクソリューションでの使用です。

2
Joe C

クラスMathを使用する

Math.abs(num);
1
Victor Urrutia

-numはInteger.MIN_VALUEのnumと等しい

 Integer.MIN_VALUE =  Integer.MIN_VALUE * -1
0
ouertani

以下を使用できます。

abs_num = (num < 0) ? -num : num;
0
CP Soni

Math.abs()、条件、またはビット単位の演算を使用しない整数xの絶対値の場合、Javaで以下の解決策が考えられます。

_(int)(((long)x*x - 1)%(double)x + 1);
_

Javaは_a%b_を_a - a/b * b_として扱うため、 "b"の符号に関係なく、結果の符号は "a"と同じになります; _(x*x-1)%x_はabs(x)-1と等しくなります;「long」の型キャストはオーバーフローを防ぐためであり、doubleはゼロによる除算を許可します。

繰り返しますが、_x = Integer.MIN_VALUE_は1を減算するためにオーバーフローを引き起こします。

0
Young

数値の絶対値を返す1行のソリューションを次に示します。

abs_number = (num < 0) ? -num : num;
0
chaitu