mirror of
https://github.com/postgres/postgres.git
synced 2025-07-28 23:42:10 +03:00
Improve type numeric's calculations for ln(), log(), exp(), pow().
Set the "rscales" for intermediate-result calculations to ensure that suitable numbers of significant digits are maintained throughout. The previous coding hadn't thought this through in any detail, and as a result could deliver results with many inaccurate digits, or in the worst cases even fail with divide-by-zero errors as a result of losing all nonzero digits of intermediate results. In exp_var(), get rid entirely of the logic that separated the calculation into integer and fractional parts: that was neither accurate nor particularly fast. The existing range-reduction method of dividing by 2^n can be applied across the full input range instead of only 0..1, as long as we are careful to set an appropriate rscale for each step. Also fix the logic in mul_var() for shortening the calculation when the caller asks for fewer output digits than an exact calculation would require. This bug doesn't affect simple multiplications since that code path asks for an exact result, but it does contribute to accuracy issues in the transcendental math functions. In passing, improve performance of mul_var() a bit by forcing the shorter input to be on the left, thus reducing the number of iterations of the outer loop and probably also reducing the number of carry-propagation steps needed. This is arguably a bug fix, but in view of the lack of field complaints, it does not seem worth the risk of back-patching. Dean Rasheed
This commit is contained in:
@ -1460,6 +1460,163 @@ select 10.0 ^ 2147483647 as overflows;
|
||||
ERROR: value overflows numeric format
|
||||
select 117743296169.0 ^ 1000000000 as overflows;
|
||||
ERROR: value overflows numeric format
|
||||
-- cases that used to return inaccurate results
|
||||
select 3.789 ^ 21;
|
||||
?column?
|
||||
--------------------------------
|
||||
1409343026052.8716016316022141
|
||||
(1 row)
|
||||
|
||||
select 3.789 ^ 35;
|
||||
?column?
|
||||
----------------------------------------
|
||||
177158169650516670809.3820586142670135
|
||||
(1 row)
|
||||
|
||||
select 1.2 ^ 345;
|
||||
?column?
|
||||
-----------------------------------------------
|
||||
2077446682327378559843444695.5827049735727869
|
||||
(1 row)
|
||||
|
||||
select 0.12 ^ (-20);
|
||||
?column?
|
||||
--------------------------------------
|
||||
2608405330458882702.5529619561355838
|
||||
(1 row)
|
||||
|
||||
-- cases that used to error out
|
||||
select 0.12 ^ (-25);
|
||||
?column?
|
||||
-------------------------------------------
|
||||
104825960103961013959336.4983657883169110
|
||||
(1 row)
|
||||
|
||||
select 0.5678 ^ (-85);
|
||||
?column?
|
||||
----------------------------------------
|
||||
782333637740774446257.7719390061997396
|
||||
(1 row)
|
||||
|
||||
--
|
||||
-- Tests for raising to non-integer powers
|
||||
--
|
||||
-- special cases
|
||||
select 0.0 ^ 0.0;
|
||||
?column?
|
||||
--------------------
|
||||
1.0000000000000000
|
||||
(1 row)
|
||||
|
||||
select (-12.34) ^ 0.0;
|
||||
?column?
|
||||
--------------------
|
||||
1.0000000000000000
|
||||
(1 row)
|
||||
|
||||
select 12.34 ^ 0.0;
|
||||
?column?
|
||||
--------------------
|
||||
1.0000000000000000
|
||||
(1 row)
|
||||
|
||||
select 0.0 ^ 12.34;
|
||||
?column?
|
||||
--------------------
|
||||
0.0000000000000000
|
||||
(1 row)
|
||||
|
||||
-- invalid inputs
|
||||
select 0.0 ^ (-12.34);
|
||||
ERROR: zero raised to a negative power is undefined
|
||||
select (-12.34) ^ 1.2;
|
||||
ERROR: a negative number raised to a non-integer power yields a complex result
|
||||
-- cases that used to generate inaccurate results
|
||||
select 32.1 ^ 9.8;
|
||||
?column?
|
||||
--------------------
|
||||
580429286790711.10
|
||||
(1 row)
|
||||
|
||||
select 32.1 ^ (-9.8);
|
||||
?column?
|
||||
----------------------------------
|
||||
0.000000000000001722862754788209
|
||||
(1 row)
|
||||
|
||||
select 12.3 ^ 45.6;
|
||||
?column?
|
||||
------------------------------------------------------
|
||||
50081010321492803393171165777624533697036806969694.9
|
||||
(1 row)
|
||||
|
||||
select 12.3 ^ (-45.6);
|
||||
?column?
|
||||
---------------------------------------------------------------------
|
||||
0.00000000000000000000000000000000000000000000000001996764828785491
|
||||
(1 row)
|
||||
|
||||
-- big test
|
||||
select 1.234 ^ 5678;
|
||||
?column?
|
||||
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
307239295662090741644584872593956173493568238595074141254349565406661439636598896798876823220904084953233015553994854875890890858118656468658643918169805277399402542281777901029346337707622181574346585989613344285010764501017625366742865066948856161360224801370482171458030533346309750557140549621313515752078638620714732831815297168231790779296290266207315344008883935010274044001522606235576584215999260117523114297033944018699691024106823438431754073086813382242140602291215149759520833200152654884259619588924545324.5973362312547382
|
||||
(1 row)
|
||||
|
||||
--
|
||||
-- Tests for EXP()
|
||||
--
|
||||
-- special cases
|
||||
select exp(0.0);
|
||||
exp
|
||||
--------------------
|
||||
1.0000000000000000
|
||||
(1 row)
|
||||
|
||||
select exp(1.0);
|
||||
exp
|
||||
--------------------
|
||||
2.7182818284590452
|
||||
(1 row)
|
||||
|
||||
select exp(1.0::numeric(71,70));
|
||||
exp
|
||||
--------------------------------------------------------------------------
|
||||
2.7182818284590452353602874713526624977572470936999595749669676277240766
|
||||
(1 row)
|
||||
|
||||
-- cases that used to generate inaccurate results
|
||||
select exp(32.999);
|
||||
exp
|
||||
---------------------
|
||||
214429043492155.053
|
||||
(1 row)
|
||||
|
||||
select exp(-32.999);
|
||||
exp
|
||||
----------------------------------
|
||||
0.000000000000004663547361468248
|
||||
(1 row)
|
||||
|
||||
select exp(123.456);
|
||||
exp
|
||||
------------------------------------------------------------
|
||||
413294435277809344957685441227343146614594393746575438.725
|
||||
(1 row)
|
||||
|
||||
select exp(-123.456);
|
||||
exp
|
||||
-------------------------------------------------------------------------
|
||||
0.000000000000000000000000000000000000000000000000000002419582541264601
|
||||
(1 row)
|
||||
|
||||
-- big test
|
||||
select exp(1234.5678);
|
||||
exp
|
||||
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
146549072930959479983482138503979804217622199675223653966270157446954995433819741094410764947112047906012815540251009949604426069672532417736057033099274204598385314594846509975629046864798765888104789074984927709616261452461385220475510438783429612447831614003668421849727379202555580791042606170523016207262965336641214601082882495255771621327088265411334088968112458492660609809762865582162764292604697957813514621259353683899630997077707406305730694385703091201347848855199354307506425820147289848677003277208302716466011827836279231.9667
|
||||
(1 row)
|
||||
|
||||
--
|
||||
-- Tests for generate_series
|
||||
--
|
||||
@ -1550,3 +1707,148 @@ select * from generate_series(1::numeric, 3::numeric) i, generate_series(1,5,i)
|
||||
3 | 4
|
||||
(10 rows)
|
||||
|
||||
--
|
||||
-- Tests for LN()
|
||||
--
|
||||
-- Invalid inputs
|
||||
select ln(-12.34);
|
||||
ERROR: cannot take logarithm of a negative number
|
||||
select ln(0.0);
|
||||
ERROR: cannot take logarithm of zero
|
||||
-- Some random tests
|
||||
select ln(1.2345678e-28);
|
||||
ln
|
||||
-----------------------------------------
|
||||
-64.26166165451762991204894255882820859
|
||||
(1 row)
|
||||
|
||||
select ln(0.0456789);
|
||||
ln
|
||||
---------------------
|
||||
-3.0861187944847439
|
||||
(1 row)
|
||||
|
||||
select ln(0.349873948359354029493948309745709580730482050975);
|
||||
ln
|
||||
-----------------------------------------------------
|
||||
-1.050182336912082775693991697979750253056317885460
|
||||
(1 row)
|
||||
|
||||
select ln(0.99949452);
|
||||
ln
|
||||
-------------------------
|
||||
-0.00050560779808326467
|
||||
(1 row)
|
||||
|
||||
select ln(1.00049687395);
|
||||
ln
|
||||
------------------------
|
||||
0.00049675054901370394
|
||||
(1 row)
|
||||
|
||||
select ln(1234.567890123456789);
|
||||
ln
|
||||
--------------------
|
||||
7.1184763012977896
|
||||
(1 row)
|
||||
|
||||
select ln(5.80397490724e5);
|
||||
ln
|
||||
--------------------
|
||||
13.271468476626518
|
||||
(1 row)
|
||||
|
||||
select ln(9.342536355e34);
|
||||
ln
|
||||
--------------------
|
||||
80.522470935524187
|
||||
(1 row)
|
||||
|
||||
--
|
||||
-- Tests for LOG() (base 10)
|
||||
--
|
||||
-- invalid inputs
|
||||
select log(-12.34);
|
||||
ERROR: cannot take logarithm of a negative number
|
||||
CONTEXT: SQL function "log" statement 1
|
||||
select log(0.0);
|
||||
ERROR: cannot take logarithm of zero
|
||||
CONTEXT: SQL function "log" statement 1
|
||||
-- some random tests
|
||||
select log(1.234567e-89);
|
||||
log
|
||||
-----------------------------------------------------------------------------------------------------
|
||||
-88.90848533591373725637496492944925187293052336306443143312825869985819779294142441287021741054275
|
||||
(1 row)
|
||||
|
||||
select log(3.4634998359873254962349856073435545);
|
||||
log
|
||||
--------------------------------------
|
||||
0.5395151714070134409152404011959981
|
||||
(1 row)
|
||||
|
||||
select log(9.999999999999999999);
|
||||
log
|
||||
----------------------
|
||||
1.000000000000000000
|
||||
(1 row)
|
||||
|
||||
select log(10.00000000000000000);
|
||||
log
|
||||
---------------------
|
||||
1.00000000000000000
|
||||
(1 row)
|
||||
|
||||
select log(10.00000000000000001);
|
||||
log
|
||||
---------------------
|
||||
1.00000000000000000
|
||||
(1 row)
|
||||
|
||||
select log(590489.45235237);
|
||||
log
|
||||
-------------------
|
||||
5.771212144411727
|
||||
(1 row)
|
||||
|
||||
--
|
||||
-- Tests for LOG() (arbitrary base)
|
||||
--
|
||||
-- invalid inputs
|
||||
select log(-12.34, 56.78);
|
||||
ERROR: cannot take logarithm of a negative number
|
||||
select log(-12.34, -56.78);
|
||||
ERROR: cannot take logarithm of a negative number
|
||||
select log(12.34, -56.78);
|
||||
ERROR: cannot take logarithm of a negative number
|
||||
select log(0.0, 12.34);
|
||||
ERROR: cannot take logarithm of zero
|
||||
select log(12.34, 0.0);
|
||||
ERROR: cannot take logarithm of zero
|
||||
select log(1.0, 12.34);
|
||||
ERROR: division by zero
|
||||
-- some random tests
|
||||
select log(1.23e-89, 6.4689e45);
|
||||
log
|
||||
------------------------------------------------------------------------------------------------
|
||||
-0.5152489207781856983977054971756484879653568168479201885425588841094788842469115325262329756
|
||||
(1 row)
|
||||
|
||||
select log(0.99923, 4.58934e34);
|
||||
log
|
||||
---------------------
|
||||
-103611.55579544132
|
||||
(1 row)
|
||||
|
||||
select log(1.000016, 8.452010e18);
|
||||
log
|
||||
--------------------
|
||||
2723830.2877097365
|
||||
(1 row)
|
||||
|
||||
select log(3.1954752e47, 9.4792021e-73);
|
||||
log
|
||||
-------------------------------------------------------------------------------------
|
||||
-1.51613372350688302142917386143459361608600157692779164475351842333265418126982165
|
||||
(1 row)
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -860,6 +860,57 @@ select 10.0 ^ -2147483647 as rounds_to_zero;
|
||||
select 10.0 ^ 2147483647 as overflows;
|
||||
select 117743296169.0 ^ 1000000000 as overflows;
|
||||
|
||||
-- cases that used to return inaccurate results
|
||||
select 3.789 ^ 21;
|
||||
select 3.789 ^ 35;
|
||||
select 1.2 ^ 345;
|
||||
select 0.12 ^ (-20);
|
||||
|
||||
-- cases that used to error out
|
||||
select 0.12 ^ (-25);
|
||||
select 0.5678 ^ (-85);
|
||||
|
||||
--
|
||||
-- Tests for raising to non-integer powers
|
||||
--
|
||||
|
||||
-- special cases
|
||||
select 0.0 ^ 0.0;
|
||||
select (-12.34) ^ 0.0;
|
||||
select 12.34 ^ 0.0;
|
||||
select 0.0 ^ 12.34;
|
||||
|
||||
-- invalid inputs
|
||||
select 0.0 ^ (-12.34);
|
||||
select (-12.34) ^ 1.2;
|
||||
|
||||
-- cases that used to generate inaccurate results
|
||||
select 32.1 ^ 9.8;
|
||||
select 32.1 ^ (-9.8);
|
||||
select 12.3 ^ 45.6;
|
||||
select 12.3 ^ (-45.6);
|
||||
|
||||
-- big test
|
||||
select 1.234 ^ 5678;
|
||||
|
||||
--
|
||||
-- Tests for EXP()
|
||||
--
|
||||
|
||||
-- special cases
|
||||
select exp(0.0);
|
||||
select exp(1.0);
|
||||
select exp(1.0::numeric(71,70));
|
||||
|
||||
-- cases that used to generate inaccurate results
|
||||
select exp(32.999);
|
||||
select exp(-32.999);
|
||||
select exp(123.456);
|
||||
select exp(-123.456);
|
||||
|
||||
-- big test
|
||||
select exp(1234.5678);
|
||||
|
||||
--
|
||||
-- Tests for generate_series
|
||||
--
|
||||
@ -880,3 +931,55 @@ select (i / (10::numeric ^ 131071))::numeric(1,0)
|
||||
select * from generate_series(1::numeric, 3::numeric) i, generate_series(i,3) j;
|
||||
select * from generate_series(1::numeric, 3::numeric) i, generate_series(1,i) j;
|
||||
select * from generate_series(1::numeric, 3::numeric) i, generate_series(1,5,i) j;
|
||||
|
||||
--
|
||||
-- Tests for LN()
|
||||
--
|
||||
|
||||
-- Invalid inputs
|
||||
select ln(-12.34);
|
||||
select ln(0.0);
|
||||
|
||||
-- Some random tests
|
||||
select ln(1.2345678e-28);
|
||||
select ln(0.0456789);
|
||||
select ln(0.349873948359354029493948309745709580730482050975);
|
||||
select ln(0.99949452);
|
||||
select ln(1.00049687395);
|
||||
select ln(1234.567890123456789);
|
||||
select ln(5.80397490724e5);
|
||||
select ln(9.342536355e34);
|
||||
|
||||
--
|
||||
-- Tests for LOG() (base 10)
|
||||
--
|
||||
|
||||
-- invalid inputs
|
||||
select log(-12.34);
|
||||
select log(0.0);
|
||||
|
||||
-- some random tests
|
||||
select log(1.234567e-89);
|
||||
select log(3.4634998359873254962349856073435545);
|
||||
select log(9.999999999999999999);
|
||||
select log(10.00000000000000000);
|
||||
select log(10.00000000000000001);
|
||||
select log(590489.45235237);
|
||||
|
||||
--
|
||||
-- Tests for LOG() (arbitrary base)
|
||||
--
|
||||
|
||||
-- invalid inputs
|
||||
select log(-12.34, 56.78);
|
||||
select log(-12.34, -56.78);
|
||||
select log(12.34, -56.78);
|
||||
select log(0.0, 12.34);
|
||||
select log(12.34, 0.0);
|
||||
select log(1.0, 12.34);
|
||||
|
||||
-- some random tests
|
||||
select log(1.23e-89, 6.4689e45);
|
||||
select log(0.99923, 4.58934e34);
|
||||
select log(1.000016, 8.452010e18);
|
||||
select log(3.1954752e47, 9.4792021e-73);
|
||||
|
@ -645,3 +645,698 @@ SELECT t1.id1, t1.result, t2.expected
|
||||
FROM num_result t1, num_exp_power_10_ln t2
|
||||
WHERE t1.id1 = t2.id
|
||||
AND t1.result != t2.expected;
|
||||
|
||||
|
||||
--
|
||||
-- Test code path for raising to integer powers
|
||||
--
|
||||
|
||||
-- base less than 1
|
||||
--
|
||||
-- bc(1) results computed with a scale of 500 and truncated using the script
|
||||
-- below, and then rounded by hand to match the precision of POW():
|
||||
--
|
||||
-- for p in {-20..20}
|
||||
-- do
|
||||
-- b="0.084738"
|
||||
-- r=$(bc -ql <<< "scale=500 ; $b^$p" | head -n 1)
|
||||
-- echo "($b, $p, $r),"
|
||||
-- done
|
||||
|
||||
WITH t(b, p, bc_result) AS (VALUES
|
||||
(0.084738, -20, 2744326694304960114888.7859130502035257),
|
||||
(0.084738, -19, 232548755422013710215.4459407000481464),
|
||||
(0.084738, -18, 19705716436950597776.2364581230406798),
|
||||
(0.084738, -17, 1669822999434319754.3627249884302211),
|
||||
(0.084738, -16, 141497461326065387.3451885900696001),
|
||||
(0.084738, -15, 11990211877848128.7928565907453178),
|
||||
(0.084738, -14, 1016026574105094.7376490817865767),
|
||||
(0.084738, -13, 86096059836517.5178789078924309),
|
||||
(0.084738, -12, 7295607918426.8214300228969888),
|
||||
(0.084738, -11, 618215223791.6519943372802450),
|
||||
(0.084738, -10, 52386321633.6570066961524534),
|
||||
(0.084738, -9, 4439112122.5928274334185666),
|
||||
(0.084738, -8, 376161483.0442710110530225),
|
||||
(0.084738, -7, 31875171.7502054369346110),
|
||||
(0.084738, -6, 2701038.3037689083149651),
|
||||
(0.084738, -5, 228880.5837847697527935),
|
||||
(0.084738, -4, 19394.8829087538193122),
|
||||
(0.084738, -3, 1643.4835879219811409),
|
||||
(0.084738, -2, 139.2655122733328379),
|
||||
(0.084738, -1, 11.8010809790176780),
|
||||
(0.084738, 0, 1),
|
||||
(0.084738, 1, .084738),
|
||||
(0.084738, 2, .007180528644),
|
||||
(0.084738, 3, .0006084636362353),
|
||||
(0.084738, 4, .0000515599916073),
|
||||
(0.084738, 5, .0000043690905688),
|
||||
(0.084738, 6, .0000003702279966),
|
||||
(0.084738, 7, .0000000313723800),
|
||||
(0.084738, 8, .0000000026584327),
|
||||
(0.084738, 9, .0000000002252703),
|
||||
(0.084738, 10, .0000000000190890),
|
||||
(0.084738, 11, .0000000000016176),
|
||||
(0.084738, 12, .0000000000001371),
|
||||
(0.084738, 13, .0000000000000116),
|
||||
(0.084738, 14, .0000000000000010),
|
||||
(0.084738, 15, .0000000000000001),
|
||||
(0.084738, 16, .0000000000000000),
|
||||
(0.084738, 17, .0000000000000000),
|
||||
(0.084738, 18, .0000000000000000),
|
||||
(0.084738, 19, .0000000000000000),
|
||||
(0.084738, 20, .0000000000000000))
|
||||
SELECT b, p, bc_result, b^p AS power, b^p - bc_result AS diff FROM t;
|
||||
|
||||
-- base greater than 1
|
||||
--
|
||||
-- bc(1) results computed with a scale of 500 and truncated using the script
|
||||
-- below, and then rounded by hand to match the precision of POW():
|
||||
--
|
||||
-- for p in {-20..20}
|
||||
-- do
|
||||
-- b="37.821637"
|
||||
-- r=$(bc -ql <<< "scale=500 ; $b^$p" | head -n 1)
|
||||
-- echo "($b, $p, $r),"
|
||||
-- done
|
||||
|
||||
WITH t(b, p, bc_result) AS (VALUES
|
||||
(37.821637, -20, .0000000000000000),
|
||||
(37.821637, -19, .0000000000000000),
|
||||
(37.821637, -18, .0000000000000000),
|
||||
(37.821637, -17, .0000000000000000),
|
||||
(37.821637, -16, .0000000000000000),
|
||||
(37.821637, -15, .0000000000000000),
|
||||
(37.821637, -14, .0000000000000000),
|
||||
(37.821637, -13, .0000000000000000),
|
||||
(37.821637, -12, .0000000000000000),
|
||||
(37.821637, -11, .0000000000000000),
|
||||
(37.821637, -10, .0000000000000002),
|
||||
(37.821637, -9, .0000000000000063),
|
||||
(37.821637, -8, .0000000000002388),
|
||||
(37.821637, -7, .0000000000090327),
|
||||
(37.821637, -6, .0000000003416316),
|
||||
(37.821637, -5, .0000000129210673),
|
||||
(37.821637, -4, .0000004886959182),
|
||||
(37.821637, -3, .0000184832796213),
|
||||
(37.821637, -2, .0006990678924066),
|
||||
(37.821637, -1, .0264398920649574),
|
||||
(37.821637, 0, 1),
|
||||
(37.821637, 1, 37.821637),
|
||||
(37.821637, 2, 1430.476225359769),
|
||||
(37.821637, 3, 54102.9525326873775219),
|
||||
(37.821637, 4, 2046262.2313195326271135),
|
||||
(37.821637, 5, 77392987.3197773940323425),
|
||||
(37.821637, 6, 2927129472.7542235178972258),
|
||||
(37.821637, 7, 110708828370.5116321107718772),
|
||||
(37.821637, 8, 4187189119324.7924539711577286),
|
||||
(37.821637, 9, 158366346921451.9852944363360812),
|
||||
(37.821637, 10, 5989674486279224.5007355092228730),
|
||||
(37.821637, 11, 226539294168214309.7083246628376531),
|
||||
(37.821637, 12, 8568086950266418559.9938312759931069),
|
||||
(37.821637, 13, 324059074417413536066.1494087598581043),
|
||||
(37.821637, 14, 12256444679171401239980.3109258799733927),
|
||||
(37.821637, 15, 463558801566202198479885.2069857662592280),
|
||||
(37.821637, 16, 17532552720991931019508170.1002855156233684),
|
||||
(37.821637, 17, 663109844696719094948877928.0672523682648687),
|
||||
(37.821637, 18, 25079899837245684700124994552.6717306599041850),
|
||||
(37.821637, 19, 948562867640665366544581398598.1275771806665398),
|
||||
(37.821637, 20, 35876200451584291931921101974730.6901038166532866))
|
||||
SELECT b, p, bc_result, b^p AS power, b^p - bc_result AS diff FROM t;
|
||||
|
||||
--
|
||||
-- Tests for raising to non-integer powers
|
||||
--
|
||||
|
||||
-- base less than 1
|
||||
--
|
||||
-- bc(1) results computed with a scale of 500 and truncated using the script
|
||||
-- below, and then rounded by hand to match the precision of POW():
|
||||
--
|
||||
-- for n in {-20..20}
|
||||
-- do
|
||||
-- b="0.06933247"
|
||||
-- p="$n.342987"
|
||||
-- r=$(bc -ql <<< "scale=500 ; e($p*l($b))" | head -n 1)
|
||||
-- echo "($b, $p, $r),"
|
||||
-- done
|
||||
|
||||
WITH t(b, p, bc_result) AS (VALUES
|
||||
(0.06933247, -20.342987, 379149253615977128356318.39406340),
|
||||
(0.06933247, -19.342987, 26287354251852125772450.59436685),
|
||||
(0.06933247, -18.342987, 1822567200045909954554.65766042),
|
||||
(0.06933247, -17.342987, 126363085720167050546.86216560),
|
||||
(0.06933247, -16.342987, 8761064849800910427.02880469),
|
||||
(0.06933247, -15.342987, 607426265866876128.15466179),
|
||||
(0.06933247, -14.342987, 42114363355427213.14899924),
|
||||
(0.06933247, -13.342987, 2919892833909256.59283660),
|
||||
(0.06933247, -12.342987, 202443382310228.51544515),
|
||||
(0.06933247, -11.342987, 14035899730722.44924025),
|
||||
(0.06933247, -10.342987, 973143597003.32229028),
|
||||
(0.06933247, -9.342987, 67470449244.92493259),
|
||||
(0.06933247, -8.342987, 4677892898.16028054),
|
||||
(0.06933247, -7.342987, 324329869.02491071),
|
||||
(0.06933247, -6.342987, 22486590.914273551),
|
||||
(0.06933247, -5.342987, 1559050.8899661435),
|
||||
(0.06933247, -4.342987, 108092.84905705095),
|
||||
(0.06933247, -3.342987, 7494.3442144625131),
|
||||
(0.06933247, -2.342987, 519.60139541889576),
|
||||
(0.06933247, -1.342987, 36.025248159838727),
|
||||
(0.06933247, 0.342987, .40036522320023350),
|
||||
(0.06933247, 1.342987, .02775830982657349),
|
||||
(0.06933247, 2.342987, .001924552183301612),
|
||||
(0.06933247, 3.342987, .0001334339565121935),
|
||||
(0.06933247, 4.342987, .000009251305786862961),
|
||||
(0.06933247, 5.342987, .0000006414158809285026),
|
||||
(0.06933247, 6.342987, .00000004447094732199898),
|
||||
(0.06933247, 7.342987, .000000003083280621074075),
|
||||
(0.06933247, 8.342987, .0000000002137714611621997),
|
||||
(0.06933247, 9.342987, .00000000001482130341788437),
|
||||
(0.06933247, 10.342987, .000000000001027597574581366),
|
||||
(0.06933247, 11.342987, .00000000000007124587801173530),
|
||||
(0.06933247, 12.342987, .000000000000004939652699872298),
|
||||
(0.06933247, 13.342987, .0000000000000003424783226243151),
|
||||
(0.06933247, 14.342987, .00000000000000002374486802900065),
|
||||
(0.06933247, 15.342987, .000000000000000001646290350274646),
|
||||
(0.06933247, 16.342987, .0000000000000000001141413763217064),
|
||||
(0.06933247, 17.342987, .000000000000000000007913703549583420),
|
||||
(0.06933247, 18.342987, .0000000000000000000005486766139403860),
|
||||
(0.06933247, 19.342987, .00000000000000000000003804110487572339),
|
||||
(0.06933247, 20.342987, .000000000000000000000002637483762562946))
|
||||
SELECT b, p, bc_result, b^p AS power, b^p - bc_result AS diff FROM t;
|
||||
|
||||
-- base greater than 1
|
||||
--
|
||||
-- bc(1) results computed with a scale of 500 and truncated using the script
|
||||
-- below, and then rounded by hand to match the precision of POW():
|
||||
--
|
||||
-- for n in {-20..20}
|
||||
-- do
|
||||
-- b="27.234987"
|
||||
-- p="$n.230957"
|
||||
-- r=$(bc -ql <<< "scale=500 ; e($p*l($b))" | head -n 1)
|
||||
-- echo "($b, $p, $r),"
|
||||
-- done
|
||||
|
||||
WITH t(b, p, bc_result) AS (VALUES
|
||||
(27.234987, -20.230957, .000000000000000000000000000009247064512095633),
|
||||
(27.234987, -19.230957, .0000000000000000000000000002518436817750859),
|
||||
(27.234987, -18.230957, .000000000000000000000000006858959399176602),
|
||||
(27.234987, -17.230957, .0000000000000000000000001868036700701026),
|
||||
(27.234987, -16.230957, .000000000000000000000005087595525911532),
|
||||
(27.234987, -15.230957, .0000000000000000000001385605980094587),
|
||||
(27.234987, -14.230957, .000000000000000000003773696085499835),
|
||||
(27.234987, -13.230957, .0000000000000000001027765638305389),
|
||||
(27.234987, -12.230957, .000000000000000002799118379829397),
|
||||
(27.234987, -11.230957, .00000000000000007623395268611469),
|
||||
(27.234987, -10.230957, .000000000000002076230710364949),
|
||||
(27.234987, -9.230957, .00000000000005654611640579014),
|
||||
(27.234987, -8.230957, .000000000001540032745212181),
|
||||
(27.234987, -7.230957, .00000000004194277179542807),
|
||||
(27.234987, -6.230957, .000000001142310844592450),
|
||||
(27.234987, -5.230957, .00000003111082100243440),
|
||||
(27.234987, -4.230957, .0000008473028055606278),
|
||||
(27.234987, -3.230957, .00002307628089450723),
|
||||
(27.234987, -2.230957, .0006284822101702527),
|
||||
(27.234987, -1.230957, .01711670482371810),
|
||||
(27.234987, 0.230957, 2.1451253063142300),
|
||||
(27.234987, 1.230957, 58.422459830839071),
|
||||
(27.234987, 2.230957, 1591.1349340009243),
|
||||
(27.234987, 3.230957, 43334.539242761031),
|
||||
(27.234987, 4.230957, 1180215.6129275865),
|
||||
(27.234987, 5.230957, 32143156.875279851),
|
||||
(27.234987, 6.230957, 875418459.63720737),
|
||||
(27.234987, 7.230957, 23842010367.779367),
|
||||
(27.234987, 8.230957, 649336842420.336290),
|
||||
(27.234987, 9.230957, 17684680461938.907402),
|
||||
(27.234987, 10.230957, 481642042480060.137900),
|
||||
(27.234987, 11.230957, 13117514765597885.614921),
|
||||
(27.234987, 12.230957, 357255344113366461.949871),
|
||||
(27.234987, 13.230957, 9729844652608062117.440722),
|
||||
(27.234987, 14.230957, 264992192625800087863.690528),
|
||||
(27.234987, 15.230957, 7217058921265161257566.469315),
|
||||
(27.234987, 16.230957, 196556505898890690402726.443417),
|
||||
(27.234987, 17.230957, 5353213882921711267539279.451015),
|
||||
(27.234987, 18.230957, 145794710509592328389185797.837767),
|
||||
(27.234987, 19.230957, 3970717045397510438979206144.696206),
|
||||
(27.234987, 20.230957, 108142427112079606637962972621.121293))
|
||||
SELECT b, p, bc_result, b^p AS power, b^p - bc_result AS diff FROM t;
|
||||
|
||||
--
|
||||
-- Tests for EXP()
|
||||
--
|
||||
|
||||
-- bc(1) results computed with a scale of 500 and truncated using the script
|
||||
-- below, and then rounded by hand to match the precision of EXP():
|
||||
--
|
||||
-- for n in {-20..20}
|
||||
-- do
|
||||
-- x="$n.29837"
|
||||
-- r=$(bc -ql <<< "scale=500 ; e($x)" | head -n 1)
|
||||
-- echo "($x, $r),"
|
||||
-- done
|
||||
|
||||
WITH t(x, bc_result) AS (VALUES
|
||||
(-20.29837, .000000001529431101152222),
|
||||
(-19.29837, .000000004157424770142192),
|
||||
(-18.29837, .00000001130105220586304),
|
||||
(-17.29837, .00000003071944485366452),
|
||||
(-16.29837, .00000008350410872606600),
|
||||
(-15.29837, .0000002269877013517336),
|
||||
(-14.29837, .0000006170165438681061),
|
||||
(-13.29837, .000001677224859055276),
|
||||
(-12.29837, .000004559169856609741),
|
||||
(-11.29837, .00001239310857408049),
|
||||
(-10.29837, .00003368796183504298),
|
||||
(-9.29837, .00009157337449401917),
|
||||
(-8.29837, .0002489222398577673),
|
||||
(-7.29837, .0006766408013046928),
|
||||
(-6.29837, .001839300394580514),
|
||||
(-5.29837, .004999736839665763),
|
||||
(-4.29837, .01359069379834070),
|
||||
(-3.29837, .03694333598818056),
|
||||
(-2.29837, .1004223988993283),
|
||||
(-1.29837, .2729763820983097),
|
||||
(0.29837, 1.3476603299656679),
|
||||
(1.29837, 3.6633205858807959),
|
||||
(2.29837, 9.9579377804197108),
|
||||
(3.29837, 27.068481317440698),
|
||||
(4.29837, 73.579760889182206),
|
||||
(5.29837, 200.01052696742555),
|
||||
(6.29837, 543.68498095607070),
|
||||
(7.29837, 1477.8890041389891),
|
||||
(8.29837, 4017.3188244304487),
|
||||
(9.29837, 10920.204759575742),
|
||||
(10.29837, 29684.194161006717),
|
||||
(11.29837, 80690.005580314652),
|
||||
(12.29837, 219338.17590722828),
|
||||
(13.29837, 596222.97785597218),
|
||||
(14.29837, 1620702.0864156289),
|
||||
(15.29837, 4405525.0308492653),
|
||||
(16.29837, 11975458.636179032),
|
||||
(17.29837, 32552671.598188404),
|
||||
(18.29837, 88487335.673150406),
|
||||
(19.29837, 240533516.60908059),
|
||||
(20.29837, 653837887.33381570))
|
||||
SELECT x, bc_result, exp(x), exp(x)-bc_result AS diff FROM t;
|
||||
|
||||
--
|
||||
-- Tests for LN()
|
||||
--
|
||||
|
||||
-- input very small
|
||||
--
|
||||
-- bc(1) results computed with a scale of 500 and truncated using the script
|
||||
-- below, and then rounded by hand to match the precision of LN():
|
||||
--
|
||||
-- for p in {1..40}
|
||||
-- do
|
||||
-- l=$(bc -ql <<< "scale=500 ; l(10^-$p)" | head -n 1)
|
||||
-- echo "('1.0e-$p', $l),"
|
||||
-- done
|
||||
|
||||
WITH t(x, bc_result) AS (VALUES
|
||||
('1.0e-1', -2.3025850929940457),
|
||||
('1.0e-2', -4.6051701859880914),
|
||||
('1.0e-3', -6.9077552789821371),
|
||||
('1.0e-4', -9.2103403719761827),
|
||||
('1.0e-5', -11.512925464970228),
|
||||
('1.0e-6', -13.815510557964274),
|
||||
('1.0e-7', -16.118095650958320),
|
||||
('1.0e-8', -18.420680743952365),
|
||||
('1.0e-9', -20.723265836946411),
|
||||
('1.0e-10', -23.025850929940457),
|
||||
('1.0e-11', -25.328436022934503),
|
||||
('1.0e-12', -27.631021115928548),
|
||||
('1.0e-13', -29.933606208922594),
|
||||
('1.0e-14', -32.236191301916640),
|
||||
('1.0e-15', -34.5387763949106853),
|
||||
('1.0e-16', -36.84136148790473094),
|
||||
('1.0e-17', -39.143946580898776628),
|
||||
('1.0e-18', -41.4465316738928223123),
|
||||
('1.0e-19', -43.74911676688686799634),
|
||||
('1.0e-20', -46.051701859880913680360),
|
||||
('1.0e-21', -48.3542869528749593643778),
|
||||
('1.0e-22', -50.65687204586900504839581),
|
||||
('1.0e-23', -52.959457138863050732413803),
|
||||
('1.0e-24', -55.2620422318570964164317949),
|
||||
('1.0e-25', -57.56462732485114210044978637),
|
||||
('1.0e-26', -59.867212417845187784467777822),
|
||||
('1.0e-27', -62.1697975108392334684857692765),
|
||||
('1.0e-28', -64.47238260383327915250376073116),
|
||||
('1.0e-29', -66.774967696827324836521752185847),
|
||||
('1.0e-30', -69.0775527898213705205397436405309),
|
||||
('1.0e-31', -71.38013788281541620455773509521529),
|
||||
('1.0e-32', -73.682722975809461888575726549899655),
|
||||
('1.0e-33', -75.9853080688035075725937180045840189),
|
||||
('1.0e-34', -78.28789316179755325661170945926838306),
|
||||
('1.0e-35', -80.590478254791598940629700913952747266),
|
||||
('1.0e-36', -82.8930633477856446246476923686371114736),
|
||||
('1.0e-37', -85.19564844077969030866568382332147568124),
|
||||
('1.0e-38', -87.498233533773735992683675278005839888842),
|
||||
('1.0e-39', -89.8008186267677816767016667326902040964430),
|
||||
('1.0e-40', -92.10340371976182736071965818737456830404406))
|
||||
SELECT x, bc_result, ln(x::numeric), ln(x::numeric)-bc_result AS diff FROM t;
|
||||
|
||||
-- input very close to but smaller than 1
|
||||
--
|
||||
-- bc(1) results computed with a scale of 500 and truncated using the script
|
||||
-- below, and then rounded by hand to match the precision of LN():
|
||||
--
|
||||
-- for p in {1..40}
|
||||
-- do
|
||||
-- l=$(bc -ql <<< "scale=500 ; l(1-10^-$p)" | head -n 1)
|
||||
-- echo "('1.0e-$p', $l),"
|
||||
-- done
|
||||
|
||||
WITH t(x, bc_result) AS (VALUES
|
||||
('1.0e-1', -.10536051565782630),
|
||||
('1.0e-2', -.010050335853501441),
|
||||
('1.0e-3', -.0010005003335835335),
|
||||
('1.0e-4', -.00010000500033335834),
|
||||
('1.0e-5', -.000010000050000333336),
|
||||
('1.0e-6', -.0000010000005000003333),
|
||||
('1.0e-7', -.00000010000000500000033),
|
||||
('1.0e-8', -.000000010000000050000000),
|
||||
('1.0e-9', -.0000000010000000005000000),
|
||||
('1.0e-10', -.00000000010000000000500000),
|
||||
('1.0e-11', -.000000000010000000000050000),
|
||||
('1.0e-12', -.0000000000010000000000005000),
|
||||
('1.0e-13', -.00000000000010000000000000500),
|
||||
('1.0e-14', -.000000000000010000000000000050),
|
||||
('1.0e-15', -.0000000000000010000000000000005),
|
||||
('1.0e-16', -.00000000000000010000000000000001),
|
||||
('1.0e-17', -.000000000000000010000000000000000),
|
||||
('1.0e-18', -.0000000000000000010000000000000000),
|
||||
('1.0e-19', -.00000000000000000010000000000000000),
|
||||
('1.0e-20', -.000000000000000000010000000000000000),
|
||||
('1.0e-21', -.0000000000000000000010000000000000000),
|
||||
('1.0e-22', -.00000000000000000000010000000000000000),
|
||||
('1.0e-23', -.000000000000000000000010000000000000000),
|
||||
('1.0e-24', -.0000000000000000000000010000000000000000),
|
||||
('1.0e-25', -.00000000000000000000000010000000000000000),
|
||||
('1.0e-26', -.000000000000000000000000010000000000000000),
|
||||
('1.0e-27', -.0000000000000000000000000010000000000000000),
|
||||
('1.0e-28', -.00000000000000000000000000010000000000000000),
|
||||
('1.0e-29', -.000000000000000000000000000010000000000000000),
|
||||
('1.0e-30', -.0000000000000000000000000000010000000000000000),
|
||||
('1.0e-31', -.00000000000000000000000000000010000000000000000),
|
||||
('1.0e-32', -.000000000000000000000000000000010000000000000000),
|
||||
('1.0e-33', -.0000000000000000000000000000000010000000000000000),
|
||||
('1.0e-34', -.00000000000000000000000000000000010000000000000000),
|
||||
('1.0e-35', -.000000000000000000000000000000000010000000000000000),
|
||||
('1.0e-36', -.0000000000000000000000000000000000010000000000000000),
|
||||
('1.0e-37', -.00000000000000000000000000000000000010000000000000000),
|
||||
('1.0e-38', -.000000000000000000000000000000000000010000000000000000),
|
||||
('1.0e-39', -.0000000000000000000000000000000000000010000000000000000),
|
||||
('1.0e-40', -.00000000000000000000000000000000000000010000000000000000))
|
||||
SELECT '1-'||x, bc_result, ln(1.0-x::numeric), ln(1.0-x::numeric)-bc_result AS diff FROM t;
|
||||
|
||||
-- input very close to but larger than 1
|
||||
--
|
||||
-- bc(1) results computed with a scale of 500 and truncated using the script
|
||||
-- below, and then rounded by hand to match the precision of LN():
|
||||
--
|
||||
-- for p in {1..40}
|
||||
-- do
|
||||
-- l=$(bc -ql <<< "scale=500 ; l(1+10^-$p)" | head -n 1)
|
||||
-- echo "('1.0e-$p', $l),"
|
||||
-- done
|
||||
|
||||
WITH t(x, bc_result) AS (VALUES
|
||||
('1.0e-1', .09531017980432486),
|
||||
('1.0e-2', .009950330853168083),
|
||||
('1.0e-3', .0009995003330835332),
|
||||
('1.0e-4', .00009999500033330834),
|
||||
('1.0e-5', .000009999950000333331),
|
||||
('1.0e-6', .0000009999995000003333),
|
||||
('1.0e-7', .00000009999999500000033),
|
||||
('1.0e-8', .000000009999999950000000),
|
||||
('1.0e-9', .0000000009999999995000000),
|
||||
('1.0e-10', .00000000009999999999500000),
|
||||
('1.0e-11', .000000000009999999999950000),
|
||||
('1.0e-12', .0000000000009999999999995000),
|
||||
('1.0e-13', .00000000000009999999999999500),
|
||||
('1.0e-14', .000000000000009999999999999950),
|
||||
('1.0e-15', .0000000000000009999999999999995),
|
||||
('1.0e-16', .00000000000000010000000000000000),
|
||||
('1.0e-17', .000000000000000010000000000000000),
|
||||
('1.0e-18', .0000000000000000010000000000000000),
|
||||
('1.0e-19', .00000000000000000010000000000000000),
|
||||
('1.0e-20', .000000000000000000010000000000000000),
|
||||
('1.0e-21', .0000000000000000000010000000000000000),
|
||||
('1.0e-22', .00000000000000000000010000000000000000),
|
||||
('1.0e-23', .000000000000000000000010000000000000000),
|
||||
('1.0e-24', .0000000000000000000000010000000000000000),
|
||||
('1.0e-25', .00000000000000000000000010000000000000000),
|
||||
('1.0e-26', .000000000000000000000000010000000000000000),
|
||||
('1.0e-27', .0000000000000000000000000010000000000000000),
|
||||
('1.0e-28', .00000000000000000000000000010000000000000000),
|
||||
('1.0e-29', .000000000000000000000000000010000000000000000),
|
||||
('1.0e-30', .0000000000000000000000000000010000000000000000),
|
||||
('1.0e-31', .00000000000000000000000000000010000000000000000),
|
||||
('1.0e-32', .000000000000000000000000000000010000000000000000),
|
||||
('1.0e-33', .0000000000000000000000000000000010000000000000000),
|
||||
('1.0e-34', .00000000000000000000000000000000010000000000000000),
|
||||
('1.0e-35', .000000000000000000000000000000000010000000000000000),
|
||||
('1.0e-36', .0000000000000000000000000000000000010000000000000000),
|
||||
('1.0e-37', .00000000000000000000000000000000000010000000000000000),
|
||||
('1.0e-38', .000000000000000000000000000000000000010000000000000000),
|
||||
('1.0e-39', .0000000000000000000000000000000000000010000000000000000),
|
||||
('1.0e-40', .00000000000000000000000000000000000000010000000000000000))
|
||||
SELECT '1+'||x, bc_result, ln(1.0+x::numeric), ln(1.0+x::numeric)-bc_result AS diff FROM t;
|
||||
|
||||
-- input very large
|
||||
--
|
||||
-- bc(1) results computed with a scale of 500 and truncated using the script
|
||||
-- below, and then rounded by hand to match the precision of LN():
|
||||
--
|
||||
-- for p in {1..40}
|
||||
-- do
|
||||
-- l=$(bc -ql <<< "scale=500 ; l(10^$p)" | head -n 1)
|
||||
-- echo "('1.0e$p', $l),"
|
||||
-- done
|
||||
|
||||
WITH t(x, bc_result) AS (VALUES
|
||||
('1.0e1', 2.3025850929940457),
|
||||
('1.0e2', 4.6051701859880914),
|
||||
('1.0e3', 6.9077552789821371),
|
||||
('1.0e4', 9.2103403719761827),
|
||||
('1.0e5', 11.512925464970228),
|
||||
('1.0e6', 13.815510557964274),
|
||||
('1.0e7', 16.118095650958320),
|
||||
('1.0e8', 18.420680743952365),
|
||||
('1.0e9', 20.723265836946411),
|
||||
('1.0e10', 23.025850929940457),
|
||||
('1.0e11', 25.328436022934503),
|
||||
('1.0e12', 27.631021115928548),
|
||||
('1.0e13', 29.933606208922594),
|
||||
('1.0e14', 32.236191301916640),
|
||||
('1.0e15', 34.538776394910685),
|
||||
('1.0e16', 36.841361487904731),
|
||||
('1.0e17', 39.143946580898777),
|
||||
('1.0e18', 41.446531673892822),
|
||||
('1.0e19', 43.749116766886868),
|
||||
('1.0e20', 46.051701859880914),
|
||||
('1.0e21', 48.354286952874959),
|
||||
('1.0e22', 50.656872045869005),
|
||||
('1.0e23', 52.959457138863051),
|
||||
('1.0e24', 55.262042231857096),
|
||||
('1.0e25', 57.564627324851142),
|
||||
('1.0e26', 59.867212417845188),
|
||||
('1.0e27', 62.169797510839233),
|
||||
('1.0e28', 64.472382603833279),
|
||||
('1.0e29', 66.774967696827325),
|
||||
('1.0e30', 69.077552789821371),
|
||||
('1.0e31', 71.380137882815416),
|
||||
('1.0e32', 73.682722975809462),
|
||||
('1.0e33', 75.985308068803508),
|
||||
('1.0e34', 78.287893161797553),
|
||||
('1.0e35', 80.590478254791599),
|
||||
('1.0e36', 82.893063347785645),
|
||||
('1.0e37', 85.195648440779690),
|
||||
('1.0e38', 87.498233533773736),
|
||||
('1.0e39', 89.800818626767782),
|
||||
('1.0e40', 92.103403719761827))
|
||||
SELECT x, bc_result, ln(x::numeric), ln(x::numeric)-bc_result AS diff FROM t;
|
||||
|
||||
-- input huge
|
||||
--
|
||||
-- bc(1) results computed with a scale of 1000 and truncated using the script
|
||||
-- below, and then rounded by hand to match the precision of LN():
|
||||
--
|
||||
-- for p in {1..10}
|
||||
-- do
|
||||
-- l=$(bc -ql <<< "scale=1000 ; l(10^${p}00)" | head -n 1)
|
||||
-- echo "('1.0e${p}00', $l),"
|
||||
-- done
|
||||
|
||||
WITH t(x, bc_result) AS (VALUES
|
||||
('1.0e100', 230.25850929940457),
|
||||
('1.0e200', 460.51701859880914),
|
||||
('1.0e300', 690.77552789821371),
|
||||
('1.0e400', 921.03403719761827),
|
||||
('1.0e500', 1151.2925464970228),
|
||||
('1.0e600', 1381.5510557964274),
|
||||
('1.0e700', 1611.8095650958320),
|
||||
('1.0e800', 1842.0680743952365),
|
||||
('1.0e900', 2072.3265836946411),
|
||||
('1.0e1000', 2302.5850929940457))
|
||||
SELECT x, bc_result, ln(x::numeric), ln(x::numeric)-bc_result AS diff FROM t;
|
||||
|
||||
--
|
||||
-- Tests for LOG() (base 10)
|
||||
--
|
||||
|
||||
-- input very small, exact result known
|
||||
WITH t(x) AS (SELECT '1e-'||n FROM generate_series(1, 100) g(n))
|
||||
SELECT x, log(x::numeric) FROM t;
|
||||
|
||||
-- input very small, non-exact results
|
||||
--
|
||||
-- bc(1) results computed with a scale of 500 and truncated using the script
|
||||
-- below, and then rounded by hand to match the precision of LN():
|
||||
--
|
||||
-- for p in {1..50..7}
|
||||
-- do
|
||||
-- for d in {9..1..3}
|
||||
-- do
|
||||
-- l=$(bc -ql <<< "scale=500 ; l($d*10^-$p) / l(10)" | head -n 1)
|
||||
-- echo "('${d}.0e-$p', $l),"
|
||||
-- done
|
||||
-- done
|
||||
|
||||
WITH t(x, bc_result) AS (VALUES
|
||||
('9.0e-1', -.04575749056067513),
|
||||
('6.0e-1', -.2218487496163564),
|
||||
('3.0e-1', -.5228787452803376),
|
||||
('9.0e-8', -7.045757490560675),
|
||||
('6.0e-8', -7.221848749616356),
|
||||
('3.0e-8', -7.522878745280338),
|
||||
('9.0e-15', -14.0457574905606751),
|
||||
('6.0e-15', -14.2218487496163564),
|
||||
('3.0e-15', -14.5228787452803376),
|
||||
('9.0e-22', -21.04575749056067512540994),
|
||||
('6.0e-22', -21.22184874961635636749123),
|
||||
('3.0e-22', -21.52287874528033756270497),
|
||||
('9.0e-29', -28.045757490560675125409944193490),
|
||||
('6.0e-29', -28.221848749616356367491233202020),
|
||||
('3.0e-29', -28.522878745280337562704972096745),
|
||||
('9.0e-36', -35.0457574905606751254099441934897693816),
|
||||
('6.0e-36', -35.2218487496163563674912332020203916640),
|
||||
('3.0e-36', -35.5228787452803375627049720967448846908),
|
||||
('9.0e-43', -42.04575749056067512540994419348976938159974227),
|
||||
('6.0e-43', -42.22184874961635636749123320202039166403168125),
|
||||
('3.0e-43', -42.52287874528033756270497209674488469079987114),
|
||||
('9.0e-50', -49.045757490560675125409944193489769381599742271618608),
|
||||
('6.0e-50', -49.221848749616356367491233202020391664031681254347196),
|
||||
('3.0e-50', -49.522878745280337562704972096744884690799871135809304))
|
||||
SELECT x, bc_result, log(x::numeric), log(x::numeric)-bc_result AS diff FROM t;
|
||||
|
||||
-- input very close to but smaller than 1
|
||||
--
|
||||
-- bc(1) results computed with a scale of 500 and truncated using the script
|
||||
-- below, and then rounded by hand to match the precision of LN():
|
||||
--
|
||||
-- for p in {1..40..7}
|
||||
-- do
|
||||
-- for d in {9..1..3}
|
||||
-- do
|
||||
-- l=$(bc -ql <<< "scale=500 ; l(1-$d*10^-$p) / l(10)" | head -n 1)
|
||||
-- echo "('${d}.0e-$p', $l),"
|
||||
-- done
|
||||
-- done
|
||||
|
||||
WITH t(x, bc_result) AS (VALUES
|
||||
('9.0e-1', -1.0000000000000000),
|
||||
('6.0e-1', -.3979400086720376),
|
||||
('3.0e-1', -.1549019599857432),
|
||||
('9.0e-8', -.000000039086505130185422),
|
||||
('6.0e-8', -.000000026057669695925208),
|
||||
('3.0e-8', -.000000013028834652530076),
|
||||
('9.0e-15', -.0000000000000039086503371292840),
|
||||
('6.0e-15', -.0000000000000026057668914195188),
|
||||
('3.0e-15', -.0000000000000013028834457097574),
|
||||
('9.0e-22', -.00000000000000000000039086503371292664),
|
||||
('6.0e-22', -.00000000000000000000026057668914195110),
|
||||
('3.0e-22', -.00000000000000000000013028834457097555),
|
||||
('9.0e-29', -.000000000000000000000000000039086503371292664),
|
||||
('6.0e-29', -.000000000000000000000000000026057668914195110),
|
||||
('3.0e-29', -.000000000000000000000000000013028834457097555),
|
||||
('9.0e-36', -.0000000000000000000000000000000000039086503371292664),
|
||||
('6.0e-36', -.0000000000000000000000000000000000026057668914195110),
|
||||
('3.0e-36', -.0000000000000000000000000000000000013028834457097555))
|
||||
SELECT '1-'||x, bc_result, log(1.0-x::numeric), log(1.0-x::numeric)-bc_result AS diff FROM t;
|
||||
|
||||
-- input very close to but larger than 1
|
||||
--
|
||||
-- bc(1) results computed with a scale of 500 and truncated using the script
|
||||
-- below, and then rounded by hand to match the precision of LN():
|
||||
--
|
||||
-- for p in {1..40..7}
|
||||
-- do
|
||||
-- for d in {9..1..3}
|
||||
-- do
|
||||
-- l=$(bc -ql <<< "scale=500 ; l(1+$d*10^-$p) / l(10)" | head -n 1)
|
||||
-- echo "('${d}.0e-$p', $l),"
|
||||
-- done
|
||||
-- done
|
||||
|
||||
WITH t(x, bc_result) AS (VALUES
|
||||
('9.0e-1', .2787536009528290),
|
||||
('6.0e-1', .2041199826559248),
|
||||
('3.0e-1', .1139433523068368),
|
||||
('9.0e-8', .000000039086501612400118),
|
||||
('6.0e-8', .000000026057668132465074),
|
||||
('3.0e-8', .000000013028834261665042),
|
||||
('9.0e-15', .0000000000000039086503371292489),
|
||||
('6.0e-15', .0000000000000026057668914195031),
|
||||
('3.0e-15', .0000000000000013028834457097535),
|
||||
('9.0e-22', .00000000000000000000039086503371292664),
|
||||
('6.0e-22', .00000000000000000000026057668914195110),
|
||||
('3.0e-22', .00000000000000000000013028834457097555),
|
||||
('9.0e-29', .000000000000000000000000000039086503371292664),
|
||||
('6.0e-29', .000000000000000000000000000026057668914195110),
|
||||
('3.0e-29', .000000000000000000000000000013028834457097555),
|
||||
('9.0e-36', .0000000000000000000000000000000000039086503371292664),
|
||||
('6.0e-36', .0000000000000000000000000000000000026057668914195110),
|
||||
('3.0e-36', .0000000000000000000000000000000000013028834457097555))
|
||||
SELECT '1+'||x, bc_result, log(1.0+x::numeric), log(1.0+x::numeric)-bc_result AS diff FROM t;
|
||||
|
||||
-- input very large, exact result known
|
||||
WITH t(x) AS (SELECT '1e'||n FROM generate_series(1, 100) g(n))
|
||||
SELECT x, log(x::numeric) FROM t;
|
||||
|
||||
-- input very large, non-exact results
|
||||
--
|
||||
-- bc(1) results computed with a scale of 500 and truncated using the script
|
||||
-- below, and then rounded by hand to match the precision of LN():
|
||||
--
|
||||
-- for p in {10..50..7}
|
||||
-- do
|
||||
-- for d in {2..9..3}
|
||||
-- do
|
||||
-- l=$(bc -ql <<< "scale=500 ; l($d*10^$p) / l(10)" | head -n 1)
|
||||
-- echo "('${d}.0e$p', $l),"
|
||||
-- done
|
||||
-- done
|
||||
|
||||
WITH t(x, bc_result) AS (VALUES
|
||||
('2.0e10', 10.301029995663981),
|
||||
('5.0e10', 10.698970004336019),
|
||||
('8.0e10', 10.903089986991944),
|
||||
('2.0e17', 17.301029995663981),
|
||||
('5.0e17', 17.698970004336019),
|
||||
('8.0e17', 17.903089986991944),
|
||||
('2.0e24', 24.301029995663981),
|
||||
('5.0e24', 24.698970004336019),
|
||||
('8.0e24', 24.903089986991944),
|
||||
('2.0e31', 31.301029995663981),
|
||||
('5.0e31', 31.698970004336019),
|
||||
('8.0e31', 31.903089986991944),
|
||||
('2.0e38', 38.301029995663981),
|
||||
('5.0e38', 38.698970004336019),
|
||||
('8.0e38', 38.903089986991944),
|
||||
('2.0e45', 45.30102999566398),
|
||||
('5.0e45', 45.69897000433602),
|
||||
('8.0e45', 45.90308998699194))
|
||||
SELECT x, bc_result, log(x::numeric), log(x::numeric)-bc_result AS diff FROM t;
|
||||
|
Reference in New Issue
Block a user