読み込み中...

Javaで学ぶ絶対値の取得方法

Javaプログラムのスクリーンショットと絶対値のグラフ Java
この記事は約33分で読めます。

【サイト内のコードはご自由に個人利用・商用利用いただけます】

この記事では、プログラムの基礎知識を前提に話を進めています。

説明のためのコードや、サンプルコードもありますので、もちろん初心者でも理解できるように表現してあります。

本記事のサンプルコードを活用して機能追加、目的を達成できるように作ってありますので、是非ご活用ください。

※この記事は、一般的にプロフェッショナルの指標とされる『実務経験10,000時間以上』を満たす現役のプログラマチームによって監修されています。

※Japanシーモアは、常に解説内容のわかりやすさや記事の品質に注力しております。不具合、分かりにくい説明や不適切な表現、動かないコードなど気になることがございましたら、記事の品質向上の為にお問い合わせフォームにてご共有いただけますと幸いです。
(送信された情報は、プライバシーポリシーのもと、厳正に取扱い、処分させていただきます。)

はじめに

Javaで絶対値を扱う場面では、単に負の数を正に変えるだけでなく、型の範囲、丸め誤差、配列やリストへの適用、独自条件によるカスタマイズまで整理しておくと実装判断が安定します。そのため、最短の方法はMath.absを使う形ですが、条件演算子やStreamBigIntegerを組み合わせる場面もあります。

初心者がつまずきやすいのは、intの最小値だけはMath.absでも正の値にできない点と、doubleの計算結果を十進数どおりに比較できない点です。こうした注意点を押さえると、Javaの絶対値取得は数値処理やデータ加工へ応用しやすくなるのが基本です。

動作確認環境
  • Java 21
  • Apache Commons Lang 3.14.0
  • Maven 3.9.x
📖 この記事で学べること
  • Javaで絶対値を取得する基本の方法
  • Math.abs、条件演算子、カスタムメソッドの使い分け
  • 配列、リスト、Streamへサンプルコードを応用する考え方
  • オーバーフローや浮動小数点数に関する注意点
  • 要件に合わせた絶対値関数のカスタマイズ

Javaと絶対値の基本

Javaで数値計算を書くとき、絶対値は距離や差分を扱うための基礎になります。その値が正か負かという符号を外し、大きさだけを比較できるため、入力値のばらつきや誤差の評価にも使われます。

その代表的な入口がjava.lang.Mathクラスのabsメソッドです。公式ドキュメントでもintlongfloatdouble向けのabsが用意されており、詳細はOracle Java SE 21 Math APIで確認できるのが目安です。

これを実装に落とすときは、最初に扱う値の型を決めます。小数を含まないカウント値ならintlong、桁数が大きい識別番号や金額計算の一部ならBigIntegerBigDecimalを検討し、型に合った絶対値の方法を選びます。

その観点では、絶対値の処理を小さなメソッドへ分けると、境界値のテストを追加しやすくなるのがポイントです。Javaの単体テストでは、正常値だけでなく最小値や最大値も入力に含めると、見落としやすい注意点を早めに発見できます。

ただし、金額計算でdoubleを使うと丸め誤差の影響を受けやすくなります。金額や数量の精度が仕様に含まれる場合は、絶対値の取得以前にBigDecimalを使う設計か、整数の最小単位で保持する設計を考える必要があるのが一般的です。

Java言語の特徴

Javaはclassを中心に処理を組み立てるオブジェクト指向の言語です。そのため、絶対値を求める処理もmainメソッドに直接書く方法から、再利用しやすいstaticメソッドへ分ける方法まで自然に拡張できます。

基本的にJavaの標準ライブラリはjava.langパッケージが暗黙的に読み込まれるため、Mathを使うだけならimport文は不要です。一方、配列をStreamへ変換するときはjava.util.Arrays、リストを扱うときはjava.util.Listjava.util.ArrayListを読み込みます。

絶対値とは

絶対値は、数値の符号を取り除いた大きさです。たとえば5の絶対値は5-5の絶対値も5になり、ゼロからの距離として理解できるのが現実的です。

具体的には、温度差、座標の距離、予測値と観測値のずれ、在庫数の増減幅など、符号より差の大きさを見たい場面で使います。ただし、Javaの整数型には表現できる範囲があるため、絶対値を取れば常に正の値になるとは限りません。

用途主な方法向く型注意点応用例
単一の整数Math.absintInteger.MIN_VALUE差分比較
単一の小数Math.absdouble丸め誤差誤差判定
条件分岐?:int境界値教材コード
配列変換forint[]破壊的変更一括補正
配列変換Arrays.streamint[]新配列生成関数型処理
リスト変換ArrayListList<Integer>null混入集計前処理
大きな整数BigInteger.absBigIntegerプリミティブ型と別APIID差分
独自ルールカスタムメソッド要件次第仕様明文化しきい値処理

これらの前提を押さえると、Javaの絶対値は「値を正にする処理」ではなく「距離として扱う処理」と整理できます。たとえば座標の差分では左右や上下の向きよりも離れ具合を見たい場面があり、そのときにMath.abs(x1 - x2)のような式が自然に使われます。

その考え方は、テストコードを書くときにも役立ちますが、これは押さえたい点です。期待値との差が小さいかを判定する場合、差分をそのまま比較するより、Math.abs(actual - expected)で符号を外してからepsilonと比べるほうが意図を読み取りやすくなります。

Javaを使用した絶対値の取得方法

結論として、通常のJavaコードではMath.absを選ぶのが最も読みやすい方法になります。条件演算子は仕組みを理解する学習用や、特殊な分岐を加える前段として役立ちますし、これが一つの目安です。

サンプルコード1:基本的な絶対値の取得

最小構成のサンプルコードでは、負のint値をMath.absへ渡します。この方法はJava初心者でも読み取りやすく、変数の入力と出力の対応を追いやすい形です。

public class Main {
    public static void main(String[] args) {
        int a = -5;
        int b = Math.abs(a);

        // このコードでは、Mathクラスのabsメソッドを使って、変数aの絶対値を取得しています。
        System.out.println("変数aの絶対値は: " + b); // 変数aの絶対値は: 5
    }
}

結果: 期待される出力は「変数aの絶対値は: 5」です。

このときaには-5が入り、bには符号を外した5が入りますが、覚えておくと役立つでしょう。ただし、Math.absは型ごとに戻り値が決まるため、intを渡すとintが返ると整理できます。

サンプルコード2:条件演算子を使った取得方法

条件演算子?:を使うと、number < 0かどうかで返す値を切り替えられます。その構造は絶対値の定義に近いため、Javaで分岐式を学ぶ初心者にも理解しやすい方法です。

public class AbsoluteValue {
    public static void main(String[] args) {
        int number = -5;
        int absoluteValue = (number < 0) ? -number : number;
        System.out.println("絶対値: " + absoluteValue);
    }
}

結果: 期待される出力は「絶対値: 5」です。

この式では、numberが負なら-numberを返し、ゼロ以上ならnumberをそのまま返します。一方、Integer.MIN_VALUEに対して-numberを評価すると範囲を超えるため、境界値を扱う処理では別の対処法が必要になります。

これに対して、条件演算子の書き方は標準APIを使わない分だけ処理の中身が見えると整理できます。教材やレビューでは、number < 0の判定、-numberによる符号反転、numberを返す分岐の三要素を一文で説明できるため、絶対値の定義をコードへ写した例として扱いやすいです。

一方、実務的なJavaコードでは、標準ライブラリに同じ意味のMath.absがあるならそちらを選ぶほうが読み手に負担をかけません。独自の方法を書く理由がある場合だけ、コメントやメソッド名で理由を残すと保守時の判断がぶれにくくなります。

サンプルコード3:Mathクラスを用いた取得方法

Math.absは、Javaで絶対値を得る標準的なメソッドです。intdoubleを同じ名前のメソッドで扱えるのは、Javaのオーバーロードによって引数の型に応じた処理が選ばれるためです。

public class Main {
    public static void main(String[] args) {
        int a = -5;
        double b = -5.3;

        int absoluteValueOfA = Math.abs(a);
        double absoluteValueOfB = Math.abs(b);

        System.out.println("aの絶対値: " + absoluteValueOfA);
        System.out.println("bの絶対値: " + absoluteValueOfB);
    }
}

結果: 期待される出力は、整数と小数それぞれの絶対値です。

aの絶対値: 5
bの絶対値: 5.3

結果: この出力例では、-55-5.35.3として表示されます。

公式ドキュメントによれば、Math.absにはintlongfloatdouble向けの定義があります。そのため、型を混在させるサンプルコードでは、戻り値の型を受ける変数も合わせておく必要があると理解できます。

同様に、メソッド名や変数名は処理の意味を伝える材料になります。absという短い名前は標準APIと近くなりすぎるため、学習用以外ではdistancedifferenceabsoluteErrorのように用途まで含めた名前を選ぶと読み手が迷いにくくなります。

使い分けると、単純な変換ではMath.abs、業務ルールを含む変換では独自メソッド、コレクション全体の変換ではmapという整理になると覚えるとよいでしょう。Javaのコードレビューでは、同じ絶対値でも「なぜその方法を選んだか」が説明できることが保守性につながります。

サンプルコード4:カスタムメソッドを作成して取得

同じ絶対値処理を複数箇所で使うなら、カスタムメソッドとして切り出す方法があります。その形にしておくと、後から入力チェックやログ出力を足すカスタマイズにもつなげやすくなると考えられます。

public class AbsoluteValueCalculator {

    public static void main(String[] args) {
        int number = -5;
        int result = getAbsoluteValue(number);
        System.out.println("絶対値の結果は: " + result);
    }

    private static int getAbsoluteValue(int number) {
        return number < 0 ? -number : number;
    }
}

結果: 期待される出力は「絶対値の結果は: 5」です。

絶対値の結果は: 5

結果: この出力例は、getAbsoluteValue-55へ変換する流れを示します。

この実装ではprivate static intのメソッドに処理を閉じ込めています。ただし、境界値まで含めて安全にしたい場合はMath.absExactlongへの変換を検討するのが現実的です。

サンプルコード5:配列内の要素の絶対値を取得

配列の値を一括で絶対値に変える場合、forループで各要素を更新する方法が分かりやすいです。その処理は元のint[]を書き換えるため、変更前の配列を残したい場合は別配列を作りますし、ここを基本と考えるとよいでしょう。

public class Main {
    public static void main(String[] args) {
        int[] array = { -1, -2, -3, -4, -5 };
        for(int i = 0; i < array.length; i++) {
            array[i] = Math.abs(array[i]);
        }

        // 絶対値が取得された配列を表示
        for(int num : array) {
            System.out.println(num);
        }
    }
}

結果: 期待される出力は、1から5までが行ごとに並ぶ形です。

1
2
3
4
5

結果: この出力例では、配列内の負の値がすべて正の値として表示されます。

この方法は配列の添字iを使うため、どの位置の値を書き換えているかを追いやすいです。一方、処理内容が「各要素へ同じ関数を適用する」だけなら、Java 8以降のStreamを使う書き方も選べます。

import java.util.Arrays;

public class Main {
    public static void main(String[] args) {
        int[] array = { -1, -2, -3, -4, -5 };
        array = Arrays.stream(array).map(Math::abs).toArray();

        // 絶対値が取得された配列を表示
        Arrays.stream(array).forEach(System.out::println);
    }
}

結果: 期待される出力は、forループ版と同じく1から5までの行です。

1
2
3
4
5

結果: この出力例は、Arrays.streammaptoArrayの流れで新しい配列が作られることを示します。

具体的には、Arrays.stream(array)IntStreamを作り、map(Math::abs)で各要素を変換し、toArray()で配列へ戻します。Javaの配列操作を広げたい場合は、Java List型完全ガイドも合わせて確認すると、コレクションとの違いを整理できると言えるでしょう。

そのため、配列のサンプルコードを読むときは「元の配列を変える処理」か「新しい配列を作る処理」かを先に確認します。前者はメモリ使用量を抑えやすく、後者は元データを残せるため、ログ出力や差分確認をしたい処理で扱いやすくなります。

具体的には、forループ版はarray[i]へ代入しており、同じ配列の中身が置き換わりますし、ここがポイントです。Stream版はtoArrayで新しい配列を作り、その参照をarrayへ代入しているため、式は短くても内部の考え方は異なります。

サンプルコード6:リスト内の要素の絶対値を取得

List<Integer>を扱う場合は、要素を順に取り出して別のリストへ絶対値を追加する方法が読みやすいです。その形なら元の値を保持したまま、変換後の値だけをabsoluteValuesとして管理できます。

import java.util.ArrayList;
import java.util.List;

public class Main {
    public static void main(String[] args) {
        List<Integer> numbers = new ArrayList<>();
        numbers.add(-5);
        numbers.add(3);
        numbers.add(-1);
        numbers.add(7);
        numbers.add(-8);

        List<Integer> absoluteValues = new ArrayList<>();
        for(Integer number : numbers) {
            absoluteValues.add(Math.abs(number));
        }

        System.out.println("元のリスト: " + numbers);
        System.out.println("絶対値のリスト: " + absoluteValues);
    }
}

結果: 期待される出力は、元のリストと絶対値へ変換したリストの二行です。

元のリスト: [-5, 3, -1, 7, -8]
絶対値のリスト: [5, 3, 1, 7, 8]

結果: この出力例では、numbersは元の符号を保ち、absoluteValuesだけが正の値に変換されています。

ただし、List<Integer>にはnullが入る可能性があります。その場合にMath.abs(number)を呼ぶとNullPointerExceptionにつながるため、入力元が不確かな処理ではObjects.nonNullなどで除外する設計が必要です。

これらのリスト処理を発展させると、負の値だけを抽出してから絶対値にする、絶対値の合計を求める、平均値との差だけを集める、といった応用ができるのが基本です。filtermapToIntsumを組み合わせると、集計前の整形処理を短く表せます。

ただし、短い式に寄せすぎると、初心者にはどの処理で値が変わったのか見えにくくなります。学習用のサンプルコードでは変数を分け、業務コードでは周辺の記法に合わせる、といった使い分けが現実的です。

サンプルコード7:ストリームを用いて絶対値の取得

Streamを使うと、配列やコレクションに同じ変換を適用する処理を短く書けるのが目安です。そのため、絶対値の取得と配列の再生成を一連の処理として読ませたい場合に向いています。

import java.util.Arrays;

public class AbsoluteValueUsingStream {
    public static void main(String[] args) {
        int[] numbers = {-4, -3, -2, -1, 0, 1, 2, 3, 4};

        int[] absoluteValues = Arrays.stream(numbers)
                                     .map(Math::abs)
                                     .toArray();

        System.out.println(Arrays.toString(absoluteValues));
    }
}

結果: 期待される出力は、符号を外した配列の文字列表現です。

[4, 3, 2, 1, 0, 1, 2, 3, 4]

結果: この出力例では、-4から4までの値が絶対値に変換されています。

このサンプルコードではMath::absというメソッド参照を使っています。ラムダ式で書くならn -> Math.abs(n)と同じ意味になり、mapは各要素を受け取って変換後の要素を返するのがポイントです。

このとき、Streamは短く書けますが、初心者が処理の順番を追う学習段階ではforループのほうが読み取りやすい場合があります。チームの規約や周辺コードに合わせて方法を選ぶと保守しやすくなります。

サンプルコード8:外部ライブラリを利用した取得方法

外部ライブラリを使う目的は、絶対値そのものを置き換えることではなく、入力値の変換や検証を補うことにあるのが一般的です。Apache Commons LangのNumberUtilsは数値文字列の扱いに使えますが、任意の文字列から数値だけを抽出するAPIではありません。

公式のAPI仕様はApache Commons Lang NumberUtilsで確認できます。そのため、次の例では数値として解釈できる文字列を渡し、変換後にMath.absで絶対値を取得します。

<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-lang3</artifactId>
    <version>3.14.0</version>
</dependency>

結果: Mavenプロジェクトでは、pom.xmlに依存関係を追加する想定です。

import org.apache.commons.lang3.math.NumberUtils;

public class AbsoluteValueUsingLibrary {
    public static void main(String[] args) {
        String input = "-123.45";
        double extractedNumber = NumberUtils.toDouble(input);
        double absoluteValue = Math.abs(extractedNumber);

        System.out.println("変換された数値: " + extractedNumber);
        System.out.println("絶対値: " + absoluteValue);
    }
}

結果: 期待される出力は、文字列から変換した数値と、その絶対値の二行です。

変換された数値: -123.45
絶対値: 123.45

結果: この出力例では、NumberUtils.toDoubledoubleへ変換し、Math.abs123.45を得ています。

注意点として、NumberUtils.toDouble("abc")のように変換できない文字列を渡すと既定値の0.0が返ります。入力エラーを見逃したくない処理では、事前にNumberUtils.isCreatableで判定する方法が使えるのが現実的です。

このライブラリ利用の注意点は、依存関係を増やす理由が明確かどうかです。絶対値を取るだけならJava標準のMath.absで足りるため、外部ライブラリは文字列変換、入力判定、既存プロジェクトとの整合など、別の目的があるときに採用します。

一般に、依存関係を追加するとビルド設定、脆弱性情報、バージョン更新の管理も必要になります。Mavenのdependencyを追加する前に、標準APIで書ける範囲と、ライブラリが解決する範囲を切り分けておくと判断しやすくなると整理できます。

Javaでの絶対値取得の応用例

Javaの絶対値取得は、単体の値を変換するだけでなく、並べ替えや判定ロジックにも応用できます。特に距離の近さで並べる処理や、二つの値の大きさを符号なしで比較する処理では、Math.absが読みやすい条件式を作ります。

こうした応用では、値を変更するのか、比較だけに使うのかを分けることが大切です。比較だけなら元の配列やリストを保持でき、変換後の値が必要なら別のコレクションへ格納すると理解できます。

これらの応用例では、絶対値を比較キーとして使うのか、変換済みの値として保存するのかで設計が分かれます。比較キーとして使うだけなら元の符号は残り、後から「元は負だったか」を判定できます。

逆に、入力値を正規化してから後続処理へ渡すなら、変換済みの配列やリストを別名で持つほうが読みやすくなると覚えるとよいでしょう。JavaではabsoluteValuesのような名前を付けるだけでも、符号を外した値であることがコード上に残ります。

サンプルコード9:絶対値を用いたソート方法

絶対値でソートする場合、プリミティブ配列のint[]に直接コンパレータは渡せません。そのため、Integer[]を使うか、リストへ変換してComparatorを指定する方法を選びます。

import java.util.Arrays;
import java.util.Comparator;

public class AbsoluteValueSort {
    public static void main(String[] args) {
        Integer[] array = {3, -1, 4, -1, -5};

        // 絶対値でのソート処理
        Arrays.sort(array, Comparator.comparingInt(Math::abs));

        // ソート結果を表示
        for (int value : array) {
            System.out.print(value + " ");
        }
    }
}

結果: 期待される出力は「-1 -1 3 4 -5 」のように絶対値の小さい順へ並んだ値です。

このサンプルコードでは、Comparator.comparingIntMath::absを渡して比較キーを作っています。一方、絶対値が同じ値の順序まで固定したい場合は、thenComparingIntで元の値を比較するなど、追加条件を入れます。

Javaのメソッド上書きや比較処理の理解を深めたい場合は、Javaでマスターするオーバーライドの記事も関連すると考えられます。ソート条件の設計では、compareの考え方を押さえるとコードの意図を読み取りやすくなります。

サンプルコード10:絶対値計算を組み込んだシミュレーション

差分比較では、値そのものの大小ではなく、ゼロからの距離を比較したい場合があります。その場合は両方の値にMath.absを適用してから差を計算すると、符号の影響を外した判定になると言えるでしょう。

public class AbsoluteValueSimulation {
    public static void main(String[] args) {
        int value1 = 5;
        int value2 = -3;

        // 絶対値の差分を計算
        int diff = Math.abs(value1) - Math.abs(value2);

        // 絶対値の差分を利用したシミュレーション処理
        if (diff > 0) {
            System.out.println("value1の絶対値がvalue2の絶対値より大きいです");
        } else if (diff < 0) {
            System.out.println("value1の絶対値がvalue2の絶対値より小さいです");
        } else {
            System.out.println("value1とvalue2の絶対値は等しいです");
        }
    }
}

結果: 期待される出力は「value1の絶対値がvalue2の絶対値より大きいです」です。

この例ではMath.abs(value1)5Math.abs(value2)3になり、差分diffは正の値になります。そのため、ifelse ifelseのうち最初の分岐が選ばれます。

ℹ️ 補足: 差分の向きまで必要な処理では、絶対値を取る前の値も残しておきますが、これは押さえたい点です。距離だけを見る処理と、増減方向を見る処理を同じ変数に混ぜると、後続の判定が読みにくくなります。

このとき、仕様書やコメントには「符号を無視して比較する」と明記しておくと誤読を避けられます。たとえば-106を通常の大小で比べる処理と、絶対値で比べる処理では結論が変わるため、条件式だけに意図を背負わせないほうが安全です。

一般に、シミュレーションやスコア計算では、値の方向と大きさを別々に保持すると後から拡張しやすくなるのが基本です。方向はInteger.signum、大きさはMath.absのように役割を分けると、分岐条件を変更するときの影響範囲が見えやすくなります。

絶対値取得時の注意点と対処法

Javaで絶対値を取得するときの注意点は、型の性質に強く関係します。doubleでは丸め誤差、intlongでは最小値のオーバーフローが代表例になるのが目安です。

そのため、単純なサンプルコードでは問題にならない値でも、入力が外部由来になると対処法が必要になります。初心者ほどMath.absだけで完結すると考えやすいため、境界値の扱いまで確認しておくと安全です。

⚠️ 注意: Math.abs(Integer.MIN_VALUE)は正のintになりません。intで表せる最大値より絶対値が1大きいため、戻り値はInteger.MIN_VALUEのままになります。

その対策として、値の型ごとにテスト観点を分ける方法があるのがポイントです。intなら01-1Integer.MAX_VALUEInteger.MIN_VALUEを確認し、doubleなら0.0-0.0NaNInfinityも候補に入ります。

ただし、すべての業務コードで全境界値を毎回処理する必要はありません。外部入力、ファイル読み込み、APIレスポンス、ユーザー入力のように値の範囲が制御しにくい場所では厚めに確認し、内部で生成した小さな値だけを扱う処理では過剰な分岐を避ける判断もあります。

浮動小数点数の絶対値取得時の問題点

浮動小数点数では、十進数の0.10.2を二進数で正確に表せない場合があるのが一般的です。そのため、0.1 + 0.20.3の差を取ると、ゼロではなく非常に小さい値が残ることがあります。

計算誤差

計算誤差を判定するときは、差の絶対値が許容範囲epsilonより小さいかを見ます。完全一致の==だけで小数を比較すると、期待と異なる判定になるかもしれません。

public class Main {
    public static void main(String[] args) {
        double a = 0.1 + 0.2;
        System.out.println("a: " + a); // a: 0.30000000000000004
        double absA = Math.abs(a - 0.3);
        System.out.println("absA: " + absA); // absA: 5.551115123125783E-17
    }
}

結果: 期待される出力は、a0.30000000000000004、差の絶対値が非常に小さい値になる形です。

この値は計算が失敗したという意味ではなく、doubleの表現方式による自然な結果です。実装パターンとしてよく見るのは、Math.abs(a - expected) < 1e-9のように許容誤差で比較する方法です。

オーバーフロー

doubleは非常に大きな値を扱えますが、計算途中で範囲を超えるとInfinityになる場合があります。絶対値だけなら符号を外す処理に近いため、最大値近くの正の値ではそのまま返ります。

public class Main {
    public static void main(String[] args) {
        double x = 1.7976931348623157E308;
        System.out.println("x: " + x); // x: 1.7976931348623157E308
        double absX = Math.abs(x);
        System.out.println("absX: " + absX); // absX: 1.7976931348623157E308
    }
}

結果: 期待される出力は、xabsXが同じ大きな正の値になる形です。

ただし、絶対値を取る前後に乗算や加算が入る処理では、Double.isFiniteで有限値か確認する設計が有効です。範囲外の値を検出したい場合は、入力チェックと例外処理を先に置くと原因を追いやすくなります。

この章の注意点は、絶対値の処理だけを見ても不具合の原因が分からない場合があることです。たとえばMath.abs(a + 1)では、問題はMath.absではなく、その前のa + 1で範囲を超えている点にあります。

そのため、対処法を考えるときは「入力」「計算途中」「絶対値取得」「出力」の順に分けて確認するのが現実的です。途中計算であふれた値に対して絶対値を取っても正しい値には戻らないため、範囲チェックはできるだけ早い位置に置くのが基本になります。

大きな数値を扱う際の注意

intの範囲は-2147483648から2147483647までです。そのため、Integer.MIN_VALUEの絶対値はintで表せず、Math.absだけでは正の値になりません。

public class Main {
    public static void main(String[] args) {
        int a = Integer.MAX_VALUE;
        System.out.println("a: " + a); // a: 2147483647
        int absA = Math.abs(a + 1);
        System.out.println("absA: " + absA); // absA: -2147483648
    }
}

結果: 期待される出力は、a2147483647absA-2147483648になる形です。

このサンプルコードでは、a + 1の時点でintの範囲を超えています。対処法として、longへ広げてから計算する、Math.addExactで例外化する、任意精度が必要ならBigIntegerを使う方法があります。

公式ドキュメントでは、範囲超過を検出するaddExactabsExactも提供されていると整理できます。Java 15以降を前提にできるなら、Math.absExactで表現不能な絶対値をArithmeticExceptionとして扱う選択肢もあります。

⚠️ 注意: 外部入力を扱う処理では、正常系のサンプルコードだけでなく、Integer.MIN_VALUELong.MIN_VALUENaNInfinityをテストデータへ含めると境界値の不具合を見つけやすくなります。

絶対値関数のカスタマイズ方法

Javaで絶対値関数をカスタマイズする目的は、業務ルールや入力制約を一箇所へ集めることです。たとえば、しきい値を超える値を無効扱いにする、nullを許容する、範囲外なら例外にする、といった方法があると理解できます。

その設計では、標準のMath.absと同じ名前に寄せすぎると誤解が生じます。独自仕様がある場合はcustomAbsoluteboundedAbsのように、制約が伝わるメソッド名にすると扱いやすいです。

一方、カスタマイズした関数を広く使う場合は、戻り値だけでなく例外方針も決めます。範囲外を0へ丸める方法は処理を継続しやすい反面、本来異常として扱うべき値を見逃す可能性があると覚えるとよいでしょう。

もっとも、入力値の一部が外れ値として混ざるデータ処理では、すべてを例外にすると処理全体が止まりやすくなります。無効値を0にする、除外する、別リストへ退避するなど、用途に合わせた方法を選ぶことが大切です。

サンプルコード11:絶対値取得関数のカスタマイズ例

次のサンプルコードでは、絶対値がしきい値を超えた場合に0を返します。この方法は、異常値を除外したい前処理や、一定範囲内の値だけを採用する応用に使えると考えられます。

public class AbsoluteValueCustom {
    public static int customAbsolute(int value, int threshold) {
        // 通常の絶対値を取得
        int absValue = Math.abs(value);

        // しきい値を超えていたら、0を返す
        if (absValue > threshold) {
            return 0;
        }
        return absValue;
    }

    public static void main(String[] args) {
        System.out.println(customAbsolute(-10, 5));  // 0
        System.out.println(customAbsolute(4, 5));   // 4
        System.out.println(customAbsolute(-4, 5));  // 4
        System.out.println(customAbsolute(6, 5));   // 0
    }
}

結果: 期待される出力は、0440が行ごとに並ぶ形です。

-10の絶対値は10となりますが、しきい値5を超えているため0となります。
4はしきい値5以下なので、絶対値4として扱われます。
-4の絶対値も4となり、しきい値5以下なので4として扱われますし、ここがポイントです。
6はしきい値5を超えているので、0として扱われますし、これが一つの目安です。

結果: この説明用の出力例は、しきい値によって返す値が変わる条件を文章で示しています。

ただし、このカスタマイズではMath.abs(value)を先に呼ぶため、Integer.MIN_VALUEの注意点は残ります。境界値も吸収したい場合は、long absValue = Math.abs((long) value)のように型を広げてから判定すると扱える範囲が広がりますが、覚えておくと役立つでしょう。

具体的には、メソッド仕様として「範囲外は0」「範囲外は例外」「範囲外は上限値へ丸める」のどれを採用するかを決めます。その判断を曖昧にすると、呼び出し側が戻り値の意味を取り違えるため、メソッド名とコメントでルールを明確にします。

Javaのアノテーションを使って入力制約を表したい場合は、Javaアノテーションの記事が参考になると言えるでしょう。たとえば@Min@Maxのような制約を使う設計では、絶対値関数の前にバリデーション層を置く考え方もあります。

これを汎用化する場合は、thresholdの意味を明確にします。上限値なのか、許容誤差なのか、異常値判定の境界なのかが曖昧なままだと、呼び出し側が同じメソッドを別々の意味で使ってしまう可能性があるのが基本です。

そのため、カスタマイズした絶対値関数には単体テストを添えるのが現実的です。customAbsolute(-10, 5)customAbsolute(5, 5)customAbsolute(6, 5)のように境界の前後を並べると、しきい値を超えたときだけ0になる仕様を確認しやすくなります。

一方、処理速度やメモリより正確さを優先する場面では、プリミティブ型だけにこだわらない判断もあります。BigIntegerは任意精度の整数を扱え、BigDecimalは十進数の精度を制御しやすいため、Javaで絶対値を扱う方法を選ぶ際の逃げ道として覚えておくと安心です。

これらを選ぶ基準は、値の由来と失敗時の扱いで決まりますし、ここを基本と考えるとよいでしょう。固定された小さな数値を扱う教材コードならMath.absで十分ですが、外部入力やファイル由来の値では、変換前の文字列チェック、型の上限確認、例外時の戻し方まで含めて設計します。

そのため、初心者がJavaの絶対値を学ぶときは、単発のサンプルコードだけで終わらせず、配列、リスト、ソート、しきい値処理へ同じ考えを移す練習が効果的です。同じMath.absでも、変換、比較、検証のどこで使うかによってコードの形が変わります。

具体的には、入力値を受け取る場所ではNumberFormatExceptionnullを想定し、計算場所ではArithmeticExceptionや丸め誤差を想定するのが目安です。出力場所では、絶対値に変換済みであることが分かるラベルや変数名を使うと、後から読む人が処理の意図を追いやすくなります。

これにより、Javaの絶対値処理は、基本構文の理解だけでなく、入力検証や例外処理まで含めた設計判断として扱えるようになります。

まとめ

Javaで絶対値を取得する方法は、単一値ならMath.abs、仕組みを明示したいなら条件演算子、再利用したいならカスタムメソッドが候補になるのがポイントです。配列やリストではforループとStreamを使い分け、元のデータを残すか書き換えるかを先に決めると実装が整理できます。

ただし、注意点としてInteger.MIN_VALUELong.MIN_VALUE、浮動小数点数の丸め誤差は必ず意識する必要があります。一般的に、外部入力や大きな値を扱うJavaコードでは、Math.absExactBigInteger、許容誤差epsilonを組み合わせると、絶対値の扱いを明確にできるのが一般的です。

応用として、絶対値によるソート、差分判定、しきい値付きのカスタマイズを組み込むと、数値処理の表現力が上がります。初心者はサンプルコードを小さく動かす前提で読み、慣れてきたらComparatorIntStreamOptionalBigDecimalなど周辺APIへ範囲を広げると理解しやすくなります。

Javaで日付や文字列も合わせて処理する場合は、Javaでうるう年を判定する記事Javaエスケープ処理の記事も役立ちますし、ここがポイントです。絶対値の方法を理解した後は、入力値の検証、変換、出力整形まで含めて設計すると、Javaの基礎文法を実用的なコードへつなげられます。

関連記事

著者: Japanシーモア編集部

Japanシーモアは、Web/IoT/APP/SYS 分野のプログラミング情報を体系的に提供するメディアです。本記事は編集部による執筆とAI支援を組み合わせて制作し、公開前に編集部が校正しています。誤りや改善案がございましたらお問い合わせよりご連絡ください。

※本記事は実在のエンジニア複数名で構成される Japanシーモア編集部が、AI支援を活用して作成・校正・公開しています。