ゲームのスコアを四捨五入して表示したいけど、Unityに四捨五入できる関数がないらしいので自分で作ろう!
参考文献
こちらの記事を参考に、好きな小数点以下の値で四捨五入できるようにしました。
コード
public float Rounding(float num,float DecPoint)//num 四捨五入する数字 DecPoint 四捨五入する位
{
float rounded;//ここに四捨五入した後の値を代入する
float DecPart=num-Mathf.FloorToInt(num);//小数部分を取り出す
int Dec1 =Mathf.FloorToInt(DecPart*Mathf.Pow(10,DecPoint));//小数部分10倍→小数点第二位以下切り捨て
int Dec2=Dec1-Mathf.FloorToInt(Dec1/10)*10;
if(Dec2>=5)
{
rounded=Mathf.CeilToInt(num*Mathf.Pow(10,DecPoint-1));
rounded/=Mathf.Pow(10,DecPoint-1);
}
else
{
rounded=Mathf.FloorToInt(num*Mathf.Pow(10,DecPoint-1));
rounded/=Mathf.Pow(10,DecPoint-1);
}
return rounded;
}
コードの解説
人間が頭で考えるのと同じように、
- 四捨五入する値を探す
- 値が5以上か判定する
- 切り上げor切り捨てする
という風に進めていきます。
あると嬉しい前提知識
・Mathf.FloorToInt() 小数点以下切り捨て
・Mathf.CeilToInt() 小数点以下切り上げ
・Mathf.Pow(a,b) aのb乗
・中学数学の基礎知識(循環小数→分数あたりがわかっていると楽かもしれない)
1.四捨五入する値を探す
ここでは「2. 値が5以上か判定する」のために値を探して取り出すことが目標です。
まずは小数部分だけを取り出します。
float DecPart=num-Mathf.FloorToInt(num);//小数部分を取り出す
四捨五入する数字から整数部分を引けば小数部分だけが残ります。
整数部分は Mathf.FloorToInt(num) で小数部分を切り捨てて求めます。
例えば3.254なら 3.254-3 で0.254だけが残ります。
小数部分が求まったら、四捨五入する数字だけを取り出します。
int Dec1 =Mathf.FloorToInt(DecPart*Mathf.Pow(10,DecPoint));//小数部分10倍→小数点第二位以下切り捨て
小数部分を10のn乗(nは四捨五入したい位)して、四捨五入する値が一の位に来るようにします。
先ほどの例だと、3.254の小数第二位を四捨五入したければ 0.254×10^2 で 25.4 になります。四捨五入したい"5"が一の位に来ましたね。
小数部分は使わないので Mathf.FloorToInt で切り捨てて25にします。
最後に一の位だけにします。
int Dec2=Dec1-Mathf.FloorToInt(Dec1/10)*10;
一の位を切り捨てて引き算しています。
先ほどの例だと、
Dec1/10 →2.5 (一の位を小数部分に逃がす)
Mathf.FloorToInt(Dec1/10) →2 (逃がした部分を切り捨てる)
Mathf.FloorToInt(Dec1/10)*10 →20 (10倍して元に戻す)
で一の位を切り捨てられます。
これを元の25から引けば晴れて5だけを取り出すことができました。
2. 値が5以上か判定する
先ほど取り出したDec2をifを使って判定します。ただのif文なので割愛します。
3. 切り上げor切り捨てする
まずは切り上げから
rounded=Mathf.CeilToInt(num*Mathf.Pow(10,DecPoint-1));
rounded/=Mathf.Pow(10,DecPoint-1);
num * Mathf.Pow(10,DecPoint-1)で切り上げたい位まで小数点を移動させます。
先ほどの例の3.254で5を切り上げるなら、3.254 * Mathf.Pow(10,2-1) で32.54になります。
これをMathf.CeilToIntで小数点以下を切り上げると、33になります。
最後に小数点を移動させた分をMathf.Pow(10,DecPoint-1)で割って元に戻せば 3.3となり、四捨五入の完成です。
切り下げの場合も同様です
rounded=Mathf.FloorToInt(num*Mathf.Pow(10,DecPoint-1));
rounded/=Mathf.Pow(10,DecPoint-1);
切り上げをしていたCeilToIntが切り下げのFloorToIntになっただけです。