Bug #38593 | prcision math POWER calculation | ||
---|---|---|---|
Submitted: | 6 Aug 2008 7:28 | Modified: | 8 Aug 2008 12:11 |
Reporter: | Hans Ginzel | Email Updates: | |
Status: | Not a Bug | Impact on me: | |
Category: | MySQL Server | Severity: | S4 (Feature request) |
Version: | 5.1.25-rc-community | OS: | Windows |
Assigned to: | CPU Architecture: | Any | |
Tags: | precision math |
[6 Aug 2008 7:28]
Hans Ginzel
[6 Aug 2008 7:54]
Sveta Smirnova
Thank you for taking the time to write to us, but this is not a bug. Please double-check the documentation available at http://dev.mysql.com/doc/ and the instructions on how to report a bug at http://bugs.mysql.com/how-to-report.php According to http://dev.mysql.com/doc/refman/5.1/en/numeric-type-overview.html: DOUBLE[(M,D)] [UNSIGNED] [ZEROFILL] ... M is the total number of digits and D is the number of digits following the decimal point. If M and D are omitted, values are stored to the limits allowed by the hardware. A double-precision floating-point number is accurate to approximately 15 decimal places. So having result only with 15 decimal places is expected. You can work around this using temporary table: mysql> create table t1(f1 double(30,20)); Query OK, 0 rows affected (0.15 sec) mysql> insert into t1 values(POWER(1+CONVERT(0.055, DECIMAL(60,30))/12,180) ); Query OK, 1 row affected (0.08 sec) mysql> select * from t1; +------------------------+ | f1 | +------------------------+ | 2.27758377248223586875 | +------------------------+ 1 row in set (0.00 sec) mysql> SELECT POWER(1+CONVERT(0.055, DECIMAL(60,30))/12,180) AS Inst; +-----------------+ | Inst | +-----------------+ | 2.2775837724822 | +-----------------+ 1 row in set (0.01 sec)
[7 Aug 2008 12:45]
Hans Ginzel
Thank you for your suggestion with temporary table. But I am still touching bad results for the standard DOUBLE data type (without any CONVERTing, precision specifying) in compare to other systems that also use standard double precision calculations. As you cite the documentation "A double-precision floating-point number is accurate to approximately 15 decimal places.". But the result of SELECT POWER(1+0.055/12, 180); is wrong on the 7th decimal place and the result is also wrong comparative to other systems using standard double precision computing. The default double computing in MySQL is worse than default computing in MS Excel!?! That is a bug. Another problem is that it is not possible to use the CONVERSION trick for DOUBLE: SELECT POWER(1+CONVERT(0.055, DOUBLE(30,20))/12, 180); ERROR 1064 (42000): You have an error in your SQL syntax near 'DOUBLE(30,20))/12, 180)' at line 1 So I request that as a feature. Or another solution. I request function say PRECISE_COMPUTE(scale, expression) so temporary table wolud not be necessary. Parametr scale would have same meaning as in program bc (standard gnu/linux binary calculator). There should be another possibility to request the precision than inserting into DOUBLE(M,D) column.
[7 Aug 2008 15:13]
Sveta Smirnova
Thank you for the feedback. > As you cite the documentation "A double-precision floating-point number is > accurate to approximately 15 decimal places.". But the result of > SELECT POWER(1+0.055/12, 180); is wrong on the 7th decimal place and the result > is also wrong comparative to other systems using standard double precision computing. You posted next results: MySQL 2.2775836364507 SELECT POWER(1+0.055/12, 180); This happens, because result of 0.055/12 is FLOAT which has exact 7 digits if its size doesn't specified. Compare: mysql> select 1+0.055/12; +------------+ | 1+0.055/12 | +------------+ | 1.0045833 | +------------+ 1 row in set (0.00 sec) mysql> select 1+CONVERT(0.055, DECIMAL(60,30))/12; +-------------------------------------+ | 1+CONVERT(0.055, DECIMAL(60,30))/12 | +-------------------------------------+ | 1.004583333333333333333333333333 | +-------------------------------------+ 1 row in set (0.00 sec) mysql> select power(1.0045833, 180); +-----------------------+ | power(1.0045833, 180) | +-----------------------+ | 2.2775701693678 | +-----------------------+ 1 row in set (0.00 sec) mysql> select power(1.004583333333333333333333333333, 180); +----------------------------------------------+ | power(1.004583333333333333333333333333, 180) | +----------------------------------------------+ | 2.2775837724822 | +----------------------------------------------+ 1 row in set (0.00 sec) But request for extension of CAST function or of new function PRECISE_COMPUTE is valid, so I mark this report as feature request.
[8 Aug 2008 12:11]
Sergei Golubchik
Temporary table isn't necessary, it's only affects the default width when you print your floating-point number. You can do the same with FORMAT function: mysql> SELECT format(POWER(1+55e-3/12,180), 30) as x; +----------------------------------+ | x | +----------------------------------+ | 2.277583772482252300051186466590 | +----------------------------------+ 1 row in set (0.00 sec) Also, note that 1+0.055/12 is NOT treated as float. It's DECIMAL, and as described in the manual the scale of a decimal division depends on div_precision_increment: mysql> set div_precision_increment=20; select 1+0.055/12; +---------------------------+ | 1+0.055/12 | +---------------------------+ | 1.00458333333333333333333 | +---------------------------+ You can force a number to be treated a double by using scientific notation - that's why I wrote 55e-3 instead of 0.055 in my first example