C++のabsは、数値の絶対値を求めるための関数です。
正の数はそのまま、負の数は符号を反転した値を返します。
整数だけでなく浮動小数点数にも利用できますが、使用するヘッダーや型によって呼び出されるオーバーロードが異なるため、正しく理解しておくことが重要です。
C++のabsとは
absは、数値の絶対値を取得するために使用します。
絶対値とは、数値から符号を取り除いた値です。
たとえば、次のようになります。
abs(10) → 10
abs(-10) → 10
abs(0) → 0
C++では一般的に、名前空間stdを付けてstd::absとして使用します。
#include <cstdlib>
#include <iostream>
int main()
{
int value = -10;
std::cout << std::abs(value) << '\n';
}
実行結果は次のとおりです。
10
absの基本的な使い方
整数の絶対値を求める
整数の絶対値を求める基本的な例です。
#include <cstdlib>
#include <iostream>
int main()
{
int a = 10;
int b = -20;
std::cout << std::abs(a) << '\n';
std::cout << std::abs(b) << '\n';
}
実行結果は次のようになります。
10
20
正の値を渡した場合はそのままの値が返されます。
負の値を渡した場合は正の値に変換された絶対値が返されます。
0を渡した場合
0の絶対値は0です。
#include <cstdlib>
#include <iostream>
int main()
{
std::cout << std::abs(0) << '\n';
}
結果は次のとおりです。
0
std::absの書き方
C++では、基本的に次のように書きます。
std::abs(value)
たとえば、
int value = -50;
int result = std::abs(value);
とすると、resultには50が格納されます。
std::cout << result;
結果は、
50
です。
absで使用するヘッダー
整数ではcstdlibを使用できる
整数型のstd::absを使用する場合は、<cstdlib>をインクルードできます。
#include <cstdlib>
例です。
#include <cstdlib>
#include <iostream>
int main()
{
int value = -100;
std::cout << std::abs(value) << '\n';
}
浮動小数点数ではcmathを使用する
doubleやfloatなどの浮動小数点数に対してstd::absを使用する場合は、通常<cmath>を使用します。
#include <cmath>
たとえば、
#include <cmath>
#include <iostream>
int main()
{
double value = -3.14;
std::cout << std::abs(value) << '\n';
}
実行結果は次のようになります。
3.14
現代のC++では、整数か浮動小数点数かに応じたstd::absのオーバーロードが用意されています。
intでabsを使う方法
intの負数を正数にする
もっとも基本的な使い方です。
#include <cstdlib>
#include <iostream>
int main()
{
int number = -25;
int result = std::abs(number);
std::cout << result << '\n';
}
結果は、
25
となります。
std::abs()は元の変数そのものを書き換えるわけではありません。
int number = -25;
int result = std::abs(number);
この場合、numberは依然として-25です。
std::cout << number << '\n'; // -25
std::cout << result << '\n'; // 25
元の変数も変更したい場合は、結果を代入します。
number = std::abs(number);
doubleでabsを使う方法
小数の絶対値も取得できる
std::absはdoubleにも利用できます。
#include <cmath>
#include <iostream>
int main()
{
double value = -12.5;
double result = std::abs(value);
std::cout << result << '\n';
}
結果は次のとおりです。
12.5
floatにも利用できる
floatにも対応しています。
#include <cmath>
#include <iostream>
int main()
{
float value = -2.5f;
float result = std::abs(value);
std::cout << result << '\n';
}
結果は、
2.5
です。
longやlong longでabsを使う方法
std::absはintだけでなく、より大きな整数型にも使用できます。
longの場合
#include <cstdlib>
#include <iostream>
int main()
{
long value = -100000L;
std::cout << std::abs(value) << '\n';
}
long longの場合
#include <cstdlib>
#include <iostream>
int main()
{
long long value = -10000000000LL;
std::cout << std::abs(value) << '\n';
}
このように、渡した型に応じて適切なオーバーロードが選択されます。
absは関数オーバーロードされている
C++のstd::absには、複数の型に対応するオーバーロードがあります。
代表的には、次のような型に利用できます。
int
long
long long
float
double
long double
そのため、同じstd::abs()という名前でも、引数の型によって適切な関数が選択されます。
std::abs(-10); // int
std::abs(-10L); // long
std::abs(-10LL); // long long
std::abs(-3.14f); // float
std::abs(-3.14); // double
std::abs(-3.14L); // long double
これがC++の関数オーバーロードの便利な点です。
absとfabsの違い
C++には、absと似た関数としてfabsがあります。
std::fabsとは
std::fabsは浮動小数点数の絶対値を求めるための関数です。
#include <cmath>
#include <iostream>
int main()
{
double value = -3.14;
std::cout << std::fabs(value) << '\n';
}
結果は、
3.14
となります。
現代のC++ではstd::absでも小数を扱える
C++では、std::absにも浮動小数点数向けのオーバーロードがあります。
そのため、
std::abs(-3.14)
でも問題ありません。
std::fabs(-3.14)
でも絶対値を取得できます。
通常のC++コードでは、整数と浮動小数点数を統一的に扱えるstd::absを使うと分かりやすいことが多いでしょう。
absをif文で使用する
std::absは条件判定にもよく利用されます。
たとえば、2つの値の差が一定以内か調べる場合です。
#include <cstdlib>
#include <iostream>
int main()
{
int a = 100;
int b = 105;
if (std::abs(a - b) <= 10)
{
std::cout << "差は10以内です\n";
}
}
a - bは、
-5
ですが、
std::abs(a - b)
によって、
5
になります。
したがって条件は成立します。
2つの数値の差を求める
数値同士の距離として使える
絶対値は、2つの数値の差を「向きを考えない距離」として扱いたい場合に便利です。
#include <cstdlib>
#include <iostream>
int main()
{
int a = 20;
int b = 35;
int difference = std::abs(a - b);
std::cout << difference << '\n';
}
結果は、
15
です。
a - bとb - aのどちらを計算しても、絶対値を取れば正の差として利用できます。
座標の距離計算にabsを使う
1次元の距離
たとえば、座標x1とx2の距離を求める場合です。
int x1 = 5;
int x2 = 12;
int distance = std::abs(x1 - x2);
結果は、
7
です。
マンハッタン距離
競技プログラミングなどでは、2次元座標のマンハッタン距離を求めるためによく使用されます。
2点、
(x1, y1)
(x2, y2)
のマンハッタン距離は、
|x1 - x2| + |y1 - y2|
です。
C++では次のように書けます。
#include <cstdlib>
#include <iostream>
int main()
{
int x1 = 2;
int y1 = 3;
int x2 = 7;
int y2 = 10;
int distance =
std::abs(x1 - x2) +
std::abs(y1 - y2);
std::cout << distance << '\n';
}
結果は、
12
です。
doubleの誤差判定にabsを使う
浮動小数点数では、単純な==による比較が意図した結果にならない場合があります。
たとえば、
double a = 0.1 + 0.2;
double b = 0.3;
について、環境や計算内容によっては、内部表現上の丸め誤差によって完全に一致しないことがあります。
そのため、差の絶対値が十分小さいか確認する方法があります。
#include <cmath>
#include <iostream>
int main()
{
double a = 0.1 + 0.2;
double b = 0.3;
if (std::abs(a - b) < 1e-10)
{
std::cout << "十分近い値です\n";
}
}
ただし、常に固定値1e-10を使えばよいわけではありません。
必要な精度や値の大きさに応じて、絶対誤差や相対誤差を考える必要があります。
absを配列やvectorで使う
vector内の値を絶対値にする
std::vectorに格納された数値に対しても使用できます。
#include <cstdlib>
#include <iostream>
#include <vector>
int main()
{
std::vector<int> values = {-10, 5, -3, 8};
for (int value : values)
{
std::cout << std::abs(value) << ' ';
}
}
結果は次のようになります。
10 5 3 8
元の要素を絶対値に変更する
配列自体の値を変更する場合は、参照を利用します。
#include <cstdlib>
#include <iostream>
#include <vector>
int main()
{
std::vector<int> values = {-10, 5, -3, 8};
for (int& value : values)
{
value = std::abs(value);
}
for (int value : values)
{
std::cout << value << ' ';
}
}
結果は、
10 5 3 8
となります。
absを関数の中で使う
絶対値を利用する処理を関数化することもできます。
#include <cstdlib>
#include <iostream>
int difference(int a, int b)
{
return std::abs(a - b);
}
int main()
{
std::cout << difference(10, 25) << '\n';
}
結果は、
15
です。
このような処理は、距離や誤差を扱うプログラムでよく利用されます。
absを使うときの重要な注意点
最小値の絶対値には注意する
整数型でstd::absを使う場合、特に重要なのが整数型の最小値です。
一般的な32ビットintでは、値域は通常、
-2147483648 ~ 2147483647
です。
この場合、
-2147483648
の絶対値は、数学的には、
2147483648
です。
しかし、この値は同じ32ビットintでは表現できません。
したがって、次のようなコードには注意が必要です。
#include <cstdlib>
#include <limits>
int main()
{
int value = std::numeric_limits<int>::min();
int result = std::abs(value);
}
INT_MINに対応する正の値がintで表現できない場合、std::absの結果をその型で表現できません。
このケースは安全に扱える通常の絶対値計算とは異なるため、特に注意が必要です。
なぜ最小値だけ問題になるのか
符号付き整数の範囲は一般的に正負で対称ではありません。
たとえば32ビットintでは、
最小値: -2147483648
最大値: 2147483647
です。
負側のほうが1つ多くなっています。
そのため、最小値だけは正の絶対値を同じ型で表せない場合があります。
unsigned型にabsは基本的に不要
unsigned intなどの符号なし整数は、そもそも負の値を表現しません。
unsigned int value = 10;
この値の絶対値は常にその値自身です。
そのため、通常は符号なし整数に対してstd::absを使う必要はありません。
また、符号なし整数同士の引き算では別の注意点があります。
たとえば、
unsigned int a = 5;
unsigned int b = 10;
auto value = a - b;
としても、単純に-5にはなりません。
符号なし整数では負数を表現できないため、モジュロ演算のルールによって大きな正の値になります。
したがって、
std::abs(a - b)
のように書けば必ず安全に差を求められる、と考えてはいけません。
符号なし整数の差を扱う場合は、計算前に型や大小関係を確認することが重要です。
absと自作の絶対値処理の違い
絶対値は条件演算子でも実装できます。
int value = -10;
int result = value < 0 ? -value : value;
結果は、
10
です。
しかし、通常は標準ライブラリのstd::absを使うほうが適切です。
int result = std::abs(value);
このほうがコードの意図が明確であり、さまざまな数値型に対応できます。
ただし、自作した場合でも最小の符号付き整数値を反転すると表現範囲を超える問題は同様に発生します。
absと三項演算子の比較
たとえば、
int result = value < 0 ? -value : value;
と、
int result = std::abs(value);
は通常の値であれば似た結果になります。
しかし、標準関数を使うことで、
std::abs(value)
というコードを見るだけで「絶対値を求めている」と分かります。
可読性の面でもstd::absを利用するメリットがあります。
std::absで複素数の絶対値を求める
C++のstd::absは、std::complexにも利用できます。
ただし、この場合の「絶対値」は単純な符号の除去ではなく、複素数の大きさを意味します。
#include <complex>
#include <iostream>
int main()
{
std::complex<double> z(3.0, 4.0);
std::cout << std::abs(z) << '\n';
}
結果は、
5
です。
複素数、
3 + 4i
の大きさは、
√(3² + 4²)
なので5になります。
通常の整数や小数のstd::absとは意味が少し異なりますが、「原点からの大きさ」という意味では共通しています。
std::absでよくある間違い
absを使えば必ず整数オーバーフローを防げると思う
std::absは絶対値を求める関数ですが、整数型の表現範囲そのものを広げるわけではありません。
たとえば、
int x = std::numeric_limits<int>::min();
について、その数学的な絶対値をintで表せない場合があります。
最小値を扱う可能性がある処理では注意が必要です。
unsigned同士の差にそのまま使う
次のようなコードにも注意が必要です。
unsigned int a = 5;
unsigned int b = 10;
auto diff = a - b;
a - bの時点で符号なし整数として計算されるため、期待する-5にはなりません。
「後からabsを付ければよい」という問題ではありません。
小数に整数用の考え方だけを適用する
浮動小数点数にもstd::absは利用できます。
double value = -3.14;
double result = std::abs(value);
したがって、小数だから必ずfabsを使わなければならないわけではありません。
C++ではstd::absを統一的に利用できます。
名前空間stdを付けない
C++では、標準ライブラリの関数として明確に呼び出すなら、
std::abs(value)
と記述するのが基本です。
単に、
abs(value)
とするよりも、どの関数を呼び出しているのかが分かりやすくなります。
absを使った実践的なサンプル
入力された整数の絶対値を表示するプログラムです。
#include <cstdlib>
#include <iostream>
int main()
{
int number;
std::cout << "整数を入力してください: ";
std::cin >> number;
std::cout
<< "絶対値: "
<< std::abs(number)
<< '\n';
}
たとえば、
-123
を入力すると、
絶対値: 123
と表示されます。
C++のabsを理解するためのポイント
C++のabsについて特に覚えておきたいのは、次の点です。
std::abs()は数値の絶対値を求める関数- 正の数はそのまま返される
- 負の数は正の絶対値として返される
- 0の絶対値は0
intだけでなくlongやlong longにも利用できるfloat、double、long doubleにも利用できる- 浮動小数点数では
<cmath>を利用する std::fabsも浮動小数点数の絶対値を求める関数- 2つの値の差や距離を求める処理で便利
- 浮動小数点数の誤差比較にも利用される
- 符号付き整数の最小値には注意が必要
unsigned同士の引き算はabsを使う前に型の挙動を確認する必要があるstd::complexでは複素数の大きさを求めるためにもstd::absが使える
C++のstd::absは非常にシンプルな関数ですが、整数、浮動小数点数、座標計算、誤差判定、競技プログラミングなど幅広い場面で利用されます。
特に、「負の値を正にする関数」とだけ覚えるのではなく、「値の符号に関係なく大きさを取得する関数」と理解すると、さまざまな処理へ応用しやすくなります。
以上、C++のcharについてでした。
最後までお読みいただき、ありがとうございました。
