10

PostgreSQL 9.2 の浮動小数点数についての初心者向けの質問があります。

最初に数値を数値型に変換することなく、浮動小数点数を直接丸める関数はありますか?

また、0.05 に近いなど、任意の測定単位で丸める機能があるかどうかを知りたいですか?

最初に数値を 10 進数形式にキャストすると、次のクエリは完全に機能します。

SELECT round(1/3.::numeric,4);

 round  
--------
 0.3333
(1 row)
Time: 0.917 ms

ただし、実際に達成したいのは次のようなものです。

SELECT round(1/3.::float,4);

現在、次のエラーが表示されます。

ERROR:  function round(double precision, integer) does not exist at character 8
Time: 0.949 ms

ありがとう

4

2 に答える 2

14

回避策は、どのバージョンの 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 を参照してくださいpublicpg_catalog


詳細

ウィキの完全な回答はこちらをご覧ください。

于 2014-01-05T13:06:08.813 に答える
13

次の行に沿って何かを行うことでこれを達成できます

select round( (21.04 /0.05 ),0)*0.05

ここ21.04で、 は四捨五入する数値で、0.05は精度です。

于 2013-04-27T00:12:17.990 に答える