HOWTO · Arduino
Arduino で float を最も近い整数に丸める方法
Arduino の round() が浮動小数点値を最も近い整数に丸める仕組み、正と負の中間値の振る舞い、任意の小数位に丸める方法を学びます。
このページの内容
Arduino の round() 関数を使うと、float から最も近い整数値を得られます。整数のちょうど中間にある値はゼロから遠ざかる方向に丸められるため、5.5 は 6、-3.5 は -4 になります。整数値が必要な場合は、結果を int に格納できます。
Arduino での round() の動作
round() は、最も近い整数を表す浮動小数点値を返します。結果を int に代入すると、整数値として格納されます。たとえば、round(3.6) は 4、round(-2.3) は -2 になります。この関数は後続の計算で使う値を変えますが、結果を元の変数に代入し直さない限り、元の変数は変わりません。
次の C++ プログラムは、整数への丸めと測定値を小数第 2 位まで丸める方法を示す完全な例です。標準 C++ の round 関数を使っており、同じ丸め規則に従います。Arduino のスケッチでは、必要に応じて round() を呼び出し、値を Serial に送ります。この例は単体で実行でき、ラベル付きの結果を表示します。
#include <cmath>
#include <cstdio>
int main() {
float positive = 5.5f;
float belowZero = -3.5f;
float measurement = 7.4567f;
int roundedPositive = static_cast<int>(std::round(positive));
int roundedBelowZero = static_cast<int>(std::round(belowZero));
float roundedMeasurement = std::round(measurement * 100.0f) / 100.0f;
std::printf("positive: %d\n", roundedPositive);
std::printf("below zero: %d\n", roundedBelowZero);
std::printf("measurement: %.2f\n", roundedMeasurement);
return 0;
}
正の値と負の値を丸める
正の値では、最も近い整数が選ばれます。中間点より小さい値は切り下げられ、中間点以上の値は切り上げられます。そのため、5.4 は 5、5.5 と 5.6 は 6 になります。ちょうど中間の値はゼロから遠ざかる方向に丸められます。
負の値にも同じ中間値の規則が適用されます。たとえば、-3.4 は -3、-3.5 と -3.6 は -4 になります。これは偶数丸めではありません。中間値を偶数の整数に近づけるために丸める方向が変わることはありません。結果を int に代入する場合は、丸めた値がその型の範囲に収まる入力を選んでください。
指定した小数桁数に丸める
round() 単体では整数に丸めます。指定した小数桁数に丸めるには、対応する 10 の累乗を掛けてから round() を呼び出し、その係数で割ります。小数第 2 位までの場合、係数は 100 です。たとえば、7.4567 はおよそ 7.46 になります。
この方法は表示や計算で多くの用途に使えますが、float の値は有限の二進精度で保存されます。小数値を正確に表現できないことがあるため、中間点に近い値では、理想的な十進演算とは異なる結果になる場合があります。より高い精度が必要な計算では元の値を保持し、表示する小数桁数を固定したいだけなら表示形式を指定してください。スケーリングしても保存値が正確になるわけではなく、利用可能な精度に応じて丸めた結果に変わるだけです。
Arduino スケッチで丸めた値を使う
スケッチでは、配列のインデックスを選ぶときや整数表示の読み取り値が必要なときなど、整数が適している箇所に結果を代入します。代入前に、丸めた値が int の範囲に収まることを確認してください。シリアル出力には Serial.println(round(sensorValue)); を使うと、丸めた値を表示できます。上の完全なプログラムはホスト側で実行する C++ の例で、Arduino のハードウェアや Arduino の Serial オブジェクトは使っていません。
マッピングの前に丸めるかどうかは任意です。map() は整数の引数を受け取るため、浮動小数点の読み取り値を先に整数へ変換する場合には丸めると便利ですが、すべてのマッピング処理で必要なわけではありません。整数値のマッピング動作については、Arduino の map() 関数を参照してください。