回避策は、どのバージョンの PostgreSQL でも機能します。
SELECT round(1/3.::numeric,4);
しかし、 「浮動小数点数を直接四捨五入する機能はありますか?」に対する答えは?、ありません。
キャストの問題
あなたはよく知られた「バグ」を報告しています。一部の PostgreSQL 関数でオーバーロードが不足しています...理由 (???): 「不足している」(!) と思いますが、@CraigRinger、@Catcall ( Craig's anser のコメントを参照 )、PostgreSQL チームは「PostgreSQL の歴史的根拠」について同意しています。
解決策は、 pg_pubLibのような集中化された再利用可能な「スニペットのライブラリ」を開発すること です。以下に説明する戦略を実装します。
キャスト戦略としてのオーバーロード
組み込みの ROUND 関数を次のようにオーバーロードできます。
CREATE FUNCTION ROUND(float,int) RETURNS NUMERIC AS $f$
SELECT ROUND($1::numeric,$2);
$f$ language SQL IMMUTABLE;
今、あなたの夢が現実になります、試してみてください
SELECT round(1/3.,4); -- 0.3333 numeric
一部のアプリケーションでは問題ない (10 進数の) NUMERIC データ型を返します... 別の方法として、関数を使用するround(1/3.,4)::float
か作成しround_tofloat()
ます。
入力データ型を保持し、浮動小数点数の精度と精度のすべての範囲を使用する他の代替手段 ( IanKenney の回答を参照) は、精度が定義されているときに float を返すことです。
CREATE or replace FUNCTION ROUND(
input float, -- the input number
accuracy float -- accuracy
) RETURNS float AS $f$
SELECT ROUND($1/accuracy)*accuracy
$f$ language SQL IMMUTABLE;
COMMENT ON FUNCTION ROUND(float,float) IS 'ROUND by accuracy.';
試す
SELECT round(21.04, 0.05); -- 21.05
SELECT round(21.04, 5::float); -- 20
SELECT round(pi(), 0.0001); -- 3.1416
SELECT round(1/3., 0.0001); -- 0.33330000000000004 (ops!)
浮動小数点の切り捨て (内部情報の損失) を避けるために、結果を「きれいにする」ことができます。たとえば、9 桁で切り捨てます。
CREATE or replace FUNCTION ROUND9(
input float, -- the input number
accuracy float -- accuracy
) RETURNS float AS $f$
SELECT (ROUND($1/accuracy)*accuracy)::numeric(99,9)::float
$f$ language SQL IMMUTABLE;
試す
SELECT round9(1/3., 0.00001); -- 0.33333 float, solved!
SELECT round9(1/3., 0.005); -- 0.335 float, ok!
PS: オーバーロード後のコマンド\df round
は、psql
次の表のように表示されます
スキーマ | 名前 | 結果 | 口論
------------+---------------------+---------------------+------------------
マイスキーマ | ラウンド | 数値 | フロート、整数
マイスキーマ | ラウンド | フロート | 浮く、浮く
pg_catalog | ラウンド | フロート | 浮く
pg_catalog | ラウンド | 数値 | 数値
pg_catalog | ラウンド | 数値 | 数値、整数
ここで、floatはスキーマを使用しない場合のmyschemadouble precision
と同義です。関数はデフォルトのものです。Guide the build in math functions を参照してください。public
pg_catalog
詳細
ウィキの完全な回答はこちらをご覧ください。