round(45.923,-1)
は 50 の結果を返します。これはなぜですか? どのように計算されますか?
(申し訳ありませんが、値が46であることを示唆するこの質問の以前のバージョンと間違えられました)
SQL ROUND() 関数は、数値を精度に丸めます...
例えば:
round(45.65, 1) は結果 = 45.7 を返します
round(45.65, -1) は結果 = 50 を返します
この場合の精度は小数点から計算されるためです。正の場合は右側の数値を考慮し、>= 5 の場合は上向きに丸め、<=4 の場合は下向きに丸めます... 同様に、負の場合は小数点の左側の精度が計算されますポイント... >= 5の場合
たとえば、round(44.65, -1) は 40 を返しますが、round(45.65, -1) は 50 を返します...
ROUND(748.58, -1) 750.00
2 番目のパラメーター: 長さは、numeric_expression が丸められる精度です。length は、tinyint、smallint、または int 型の式でなければなりません。length が正の数値の場合、numeric_expression は length で指定された小数点以下の桁数に丸められます。length が負の数の場合、numeric_expression は length で指定されたとおりに小数点の左側で丸められます。
方法については、(正の) 浮動小数点数を最も近い整数に丸める方法を検討することから始めます。float を int にキャストすると、切り捨てられます。(正の) float に 0.5 を追加すると、切り上げたいときに整数部分が正確にインクリメントされます (小数部分が >= 0.5 の場合)。これにより、以下が得られます。
double round(double x) {
return (long long)(x + 0.5);
}
精度パラメーターのサポートを追加するには、(たとえばround(123456.789, -3)
) 500 を追加して千の位で切り捨てることは、基本的に 0.5 を追加することと同じであり、最も近い整数に丸めることに注意してください。小数点の位置が異なるだけです。基数ポイントを移動するには、左シフト操作と右シフト操作が必要です。これは、シフト量に累乗した基数を掛けることと同じです。つまり、基数 2のおよび と0x1234 >> 3
同じです。基数 10 の場合:0x1234 / 2**3
0x1234 * 2**-3
123456.789 >> 3 == 123456.789 / 10**3 == 123456.789 * 10**-3 == 123.456789
の場合round(123456.789, -3)
、これは上記の乗算を実行して小数点を移動し、0.5 を加算し、切り捨て、次に逆の乗算を実行して小数点を戻すことができることを意味します。
double round(double x, double p) {
return ((long long)((x * pow10(p))) + 0.5) * pow10(-p);
}
0.5 を追加して切り捨てることによる丸めは、負でない数値に対しては正常に機能しますが、負の数値に対しては間違った方法で丸められます。いくつかの解決策があります。効率的なsign()
関数 (数値が <0、==0、>0 のいずれであるかに応じて、それぞれ -1、0、または 1 を返す) がある場合は、次のことができます。
double round(double x, double p) {
return ((long long)((x * pow10(p))) + sign(x) * 0.5) * pow10(-p);
}
そうでない場合は、次のとおりです。
double round(double x, double p) {
if (x<0)
return - round(-x, p);
return ((long long)((x * pow10(p))) + 0.5) * pow10(-p);
}
50台になる見込みです。
ラウンド (45.923, 0) => 46
expl: 10 進数以外の最後の桁は丸められます (5)。desicion は次の桁に基づいています (9) 9 は上位半分にあるため、5 は 6 に切り上げられます。
ラウンド(45.923, 1) => 45.9
expl: 最初の 10 進数は丸められます (9)。desicion は次の桁に基づいています (2) 2 は下半分にあり、したがって 9 は 9 のままです
あなたの場合: round(45.923, 1-) => 45.92
expl: 最後の 2 番目の非 10 進数は丸められ (4)、desicion は次の数字に基づいています (5) 5 は上半分にあり、したがって 4 は 5 に切り上げられ、数字の残りは次の値で埋められます。 0秒
MySQLではそうではありません:
mysql> select round(45.923,-1);
+------------------+
| round(45.923,-1) |
+------------------+
| 50 |
+------------------+
1 row in set (0.00 sec)
Sql Server 2005 の場合:
select round(45.923,-1)
------
50.000
これを実行しているデータベースは何ですか?