All the PostgreSQL time types、小数点以下6桁をマイクロ秒の分解能を持っています。
最も近い偶数マイクロ秒に丸めても、マイクロ秒の解像度ではありません。
その動作は、私には普通の方法であるround half-upと一貫しています。 > = 0.5は切り上げ、それ以外は切り捨てる。 7桁目が5
test=# select '2000-01-01T00:00:00.5024585Z'::timestamp;
timestamp
----------------------------
2000-01-01 00:00:00.502459
(1 row)
0.5024584999999 0.502458までのラウンドであるため、7桁目が4
test=# select '2000-01-01T00:00:00.5024584999999Z'::timestamp;
timestamp
----------------------------
2000-01-01 00:00:00.502458
(1 row)
あるので
0.5024585小数点以下6桁に丸めハーフアップは0.502459までの丸め
上記のことは異常であるようです。 '2000-01-01T00:00:00.5024235Z'から '2000-01-01T00:00:00.5024355Z'にステップインすることは、ハーフ偶数丸めと一貫しています。
私は、入力の浮動小数点秒から浮動小数点エラーへの変換が、timestamp
が使用する整数マイクロ秒に変換されているためと推測しています。
test=# select '2000-01-01T00:00:00.5024235Z'::timestamp;
timestamp
----------------------------
2000-01-01 00:00:00.502424
(1 row)
test=# select '2000-01-01T00:00:00.5024245Z'::timestamp;
timestamp
----------------------------
2000-01-01 00:00:00.502425
(1 row)
test=# select '2000-01-01T00:00:00.5024255Z'::timestamp;
timestamp
----------------------------
2000-01-01 00:00:00.502425
(1 row)
test=# select '2000-01-01T00:00:00.5024265Z'::timestamp;
timestamp
----------------------------
2000-01-01 00:00:00.502426
(1 row)
test=# select '2000-01-01T00:00:00.5024275Z'::timestamp;
timestamp
----------------------------
2000-01-01 00:00:00.502428
(1 row)
test=# select '2000-01-01T00:00:00.5024285Z'::timestamp;
timestamp
----------------------------
2000-01-01 00:00:00.502428
(1 row)
test=# select '2000-01-01T00:00:00.5024295Z'::timestamp;
timestamp
---------------------------
2000-01-01 00:00:00.50243
(1 row)
test=# select '2000-01-01T00:00:00.5024305Z'::timestamp;
timestamp
---------------------------
2000-01-01 00:00:00.50243
(1 row)
test=# select '2000-01-01T00:00:00.5024315Z'::timestamp;
timestamp
----------------------------
2000-01-01 00:00:00.502432
(1 row)
test=# select '2000-01-01T00:00:00.5024325Z'::timestamp;
timestamp
----------------------------
2000-01-01 00:00:00.502432
(1 row)
test=# select '2000-01-01T00:00:00.5024335Z'::timestamp;
timestamp
----------------------------
2000-01-01 00:00:00.502434
(1 row)
test=# select '2000-01-01T00:00:00.5024345Z'::timestamp;
timestamp
----------------------------
2000-01-01 00:00:00.502434
(1 row)
test=# select '2000-01-01T00:00:00.5024355Z'::timestamp;
timestamp
----------------------------
2000-01-01 00:00:00.502436
(1 row)
これはまた、interval N microsecond
で再生されます。小数点以下の桁数が少ないほど浮動小数点エラーが少なくなります。
test=# select interval '0.5 microsecond';
interval
----------
00:00:00
(1 row)
test=# select interval '1.5 microsecond';
interval
-----------------
00:00:00.000002
(1 row)
test=# select interval '2.5 microsecond';
interval
-----------------
00:00:00.000002
(1 row)
test=# select interval '3.5 microsecond';
interval
-----------------
00:00:00.000004
(1 row)
test=# select interval '4.5 microsecond';
interval
-----------------
00:00:00.000004
(1 row)
test=# select interval '5.5 microsecond';
interval
-----------------
00:00:00.000006
(1 row)
test=# select interval '6.5 microsecond';
interval
-----------------
00:00:00.000006
(1 row)
小さなCプログラムでは、丸め影響を与える7つの小数点以下の桁数での単精度浮動小数点数と浮動小数点の精度に問題があると確認しました。
#include <math.h>
#include <stdio.h>
int main() {
float nums[] = {
0.5024235f,
0.5024245f,
0.5024255f,
0.5024265f,
0.5024275f,
0.5024285f,
0.5024295f,
0.5024305f,
NAN
};
for(int i = 0; !isnan(nums[i]); i++) {
printf("%0.8f\n", nums[i]);
}
}
これが生成します。
0.50242352
0.50242448
0.50242549
0.50242651
0.50242752
0.50242847
0.50242949
0.50243050
ダブルスとのに対し、全く問題ありません。
0.50242350
0.50242450
0.50242550
0.50242650
0.50242750
0.50242850
0.50242950
0.50243050
間違いなく。私はPostgreSQLのソースコードを調べて、二重に変換するstrtodを使用します。 – ifotneak