Log On
Embarcadero Home
Watch, Follow, &
Connect with Us
Share This
QualityCentral
Communities
Articles
Blogs
Resources
Downloads
Help
QualityCentral
Delphi-BCB
RTL
Delphi
Arithmetic
ConvUtils
Date - Time
DateUtils
File Management
Format + Float
Input/Output
Math Unit
Memory, Pointer, Address
Null-terminated strings
Other Classes
Other RTL
Pascal Strings
Regular Expressions
RTL Exceptions
Text Files
Thread support
Typed/Untyped Files
WinAPI
You are not logged in.
Help
Print
Public Report
Report From:
Delphi-BCB/RTL/Delphi/Math Unit
[ Add a report in this area ]
Report #:
79687
Status:
Open
RoundTo gives wrong results
Project:
Delphi
Build #:
14.0.3593.25826
Version:
14.0
Submitted By:
John Herbster
Report Type:
Basic functionality failure
Date Reported:
11/20/2009 9:56:10 AM
Severity:
Infrequently encountered problem
Last Updated:
3/20/2012 2:24:39 AM
Platform:
All versions
Internal Tracking #:
273982
Resolution:
None
(Resolution Comments)
Resolved in Build:
:
None
Duplicate of:
None
Voting and Rating
Overall Rating:
No Ratings Yet
0.00 out of 5
Total Votes:
31
Description
[JJS]
Even after much hand wringing, coding, and testing, <g>
A little more testing shows that there are still problems with the Math.RoundTo routine in D2010.
The criterion for correct result that I use is, where D, N, and NDFD (number decimal fraction digits) are integer variables and X, Y, and Z are variables of identical floating point types (single, double, or extended) and where
D := 10^NDFD;
N > 0
X := (N*10+5)/(D*10);
Z := RoundTo(X,-NDFD);
and
if N is even Y := N/D else Y := (N+1)/D;
then the following should be true
Z = Y.
A lesser criterion (called "normalization") is that where Z
is the result of the above RoundTo and W is a variable from
the same type as Z and where
W := round(Z*D)/D;
then the following should be true
W = Z.
The attached test program, T_QC79687_0a, tests both criteria.
This is a program for testing results of the decimal rounding functions. It was written to try to test any changes in the decimal fraction rounding function Math.RoundTo that may have been incorporated into Delphi versions beyond D7. While I am not privy to the exact changes that have been made to the rounding function, it has be suggested that something like the RoundToEX_JOH_IA32_2 function (written by John O'Harrow as copied on 2009.01.24 from QualityCentral report #14394 filed by Dennis Christensen on 2005.07.14) may be the basis for changes to Math.RoundTo in later Delphi versions later than D7.
This program tests the following four functions each with single, double, and extended input and output parameters:
Math.RoundTo
RoundToEX_JOH_IA32_2
RoundToEX_JH1_Pas2
DecimalRounding_JH1.DecimalRound(Sgl,Dbl,Ext)
The DecimalRounding_JH1 was writen by John Herbster and is inclluded in the attachments.
At present, this program only tests the accuracy of the rounding results for inputs which are halfway between adjacent points in the range of possible outputs.
Doing just a 100 tests, here are examples of problems found:
Testing RoundToEX_JOH_IA32_2(*,-2) with type extended input and output.
ER RoundToEX_JOH_IA32_2(95/1000,-2) [NotNormalized]
Inp=0.09499999999999999999891579782751449556599254719913005828857421875
Out=0.09999999999999999999457898913757247782996273599565029144287109375
NoR=0.1000000000000000000013552527156068805425093160010874271392822265625
SBR=0.1000000000000000000013552527156068805425093160010874271392822265625
ER RoundToEX_JOH_IA32_2(105/1000,-2) [NotNormalized]
Inp=0.1049999999999999999970184440256648628064795047976076602935791015625
Out=0.09999999999999999999457898913757247782996273599565029144287109375
NoR=0.1000000000000000000013552527156068805425093160010874271392822265625
SBR=0.1000000000000000000013552527156068805425093160010874271392822265625
ER RoundToEX_JOH_IA32_2(295/1000,-2) [WrongWay]
Inp=0.29499999999999999998807377610265945122591801919043064117431640625
Out=0.28999999999999999999241058479260146896194783039391040802001953125
SBR=0.3000000000000000000108420217248550443400745280086994171142578125
Inp=Input; Out=Output; NoR=NormalizedOutput; SBR=CorrectBankersOutput
Tested from 0/100 to 100/100.
30 errors in 100 tests (29 NotNormalized, 1 WrongWay)
Testing RoundToEX_JH1_Pas2(*,-2) with type extended input and output.
ER RoundToEX_JH1_Pas2(295/1000,-2) [WrongWay]
Inp=0.29499999999999999998807377610265945122591801919043064117431640625
Out=0.28999999999999999999241058479260146896194783039391040802001953125
SBR=0.3000000000000000000108420217248550443400745280086994171142578125
Inp=Input; Out=Output; NoR=NormalizedOutput; SBR=CorrectBankersOutput
Tested from 0/100 to 100/100.
1 error in 100 tests (1 WrongWay)
One can argue about the WrongWay error; but I would like to see an excuse for returning any result x where x <> round(x*100)/100 assuming that two decimal fraction digits was asked for.
Note that the DecimalRounding(Ext,Dbl, and Sgl) functions all seem to always give the expected bankers rounding result *and* a optional parameter allows them to round according to about 9 different rules. To use these as a replacement for RoundTo, I suggest that
(1) they should be checked by someone other than myself;
(2) consideration be given to letting them all overload the same, perhaps new, name; and
(3) other kinds of testing should also be done.
Please send me any comments, suggestions, or questions.
--JohnH, 2009.11.28, herb-sci1@sbcglobal.net, (h)281-531-4423, (c)291-782-8991.
Steps to Reproduce:
To replicate the problems, compile and execute the attached program, T_QC79687_0a.
Workarounds
None
Attachment
T_QC79687 091128b.zip
Comments
Ralf Stocker at 11/20/2009 12:17:19 PM
-
Hi John,
you are the floating point guru...that means you have to say whats to do and what lines must be corrected. Otherwise, I fear, nothing happens...nobody has your floating point knowledge.
John Herbster at 11/20/2009 1:01:06 PM
-
Ralf, I will ponder the possibilities. It is so easy to find problems in this area; but more dificult to make good recommendations. There is however one easy suggestion that I might be able to work up. Thanks for the advice. Rgds, JohnH
John Herbster at 11/21/2009 10:02:22 AM
-
Mr Takahashi,
Thanks for noticing this report.
I am preparing more information, test results, and a suggested improvement.
I will post here when it is ready.
Regards, JohnH
John Herbster at 11/28/2009 10:29:35 AM
-
New test program, T_QC79687_0a, is uploaded to attachments.
Please let me know of all problems and suggestions.
Thanks, John Herbster, herb-sci1@sbcglobal.net, (h)281-531-4423, (c)281-782-8991.
John Herbster at 11/27/2009 2:45:27 PM
-
A comment to all readers:
I have gotten comments recently as well as in the distance past that the number of digits I show, like
xin=0.09499999999999999999891579782751449556599254719913005828857421875
xre=0.09999999999999999999457898913757247782996273599565029144287109375
xnr=0.1000000000000000000013552527156068805425093160010874271392822265625
looks excessive and that according to the help extended has 10-20 significand digits. So why do I show 66 or 68 significand digits?
My purpose in using the extra digits to show the *exact* number represented by the contents of a floating binary point variable, so that we can compare its value against decimal fraction numbers like 0.1 and determine whether the above xre or xnr is closer to 0.1 and so that we can determine whether the floating point representations like from StrToFloat('0.05') are closer to 0.0 or closer to 0.1.
Regards, JohnH
View Your Reports
Search
Server Response from: ETNACODE01
Developer Tools
Blackfish SQL
C++Builder
Delphi
FireMonkey
Prism
InterBase
JBuilder
J Optimizer
HTML5 Builder
3rdRail & TurboRuby
Database Tools
Change Manager
DBArtisan
DB Optimizer
ER/Studio
Performance Center
Rapid SQL
Technical Articles
Tutorials
White Papers
Press Releases
Newsletters
Add Content (GetPublished)
Audio
Audio & Video
Video
Bugs & Suggestions (QualityCentral)
Discussion Forums
Examples (CodeCentral)
Tags
Technology Partners
Downloads
Free Trials
Registered User Downloads
Beta Programs
Add Content (GetPublished)
Articles
Blogs
Bugs & Suggestions (QualityCentral)
Discussion Forums
Examples (CodeCentral)
Member Services
About
Connect with Us