- Feature Articles
- CodeSOD
- Error'd
- Forums
-
Other Articles
- Random Article
- Other Series
- Alex's Soapbox
- Announcements
- Best of…
- Best of Email
- Best of the Sidebar
- Bring Your Own Code
- Coded Smorgasbord
- Mandatory Fun Day
- Off Topic
- Representative Line
- News Roundup
- Editor's Soapbox
- Software on the Rocks
- Souvenir Potpourri
- Sponsor Post
- Tales from the Interview
- The Daily WTF: Live
- Virtudyne
Admin
Rounding numbers other than to powers of 2 for anything which isn't presentation is always something which merits a double-check for sanity anyway.
Admin
TRWTF is bankers rounding especially when it's default one in a framework of choice. If I want rounding error mitigation mechanism, I'll ask for it.
Admin
TRWTF is using binary floating point numbers to represent fixed-point decimals. And if you round in binary, you better round ties to the next even number and not always away from zero (preferably by letting your FPU do that for you, not with some genius hand-made routine).
Admin
Admin
Admin
Or more precisely exactly 1/2 of the last significant digit...the irony is that many of these values can NOT be exactly specified in a binary number and therefore bankers rounding should NEVER occur (everything will be above or below the 1/2 way point)...which makes the end results really interesting.
The (admittedly horrible) string based method actually avoids this issue.
Admin
Banker's rounding is the default in IEEE floating point hardware.
Admin
And all the functionality that strings may lack (e.g. "14" / 2 = 7.0) can easily be implemented by operator overloading.
Ah, I just love strings!
Admin
And of course TRWTF is non-ascii characters in comments.
Admin
This is not how it is done in The Book of Five Rings!
Admin
Admin
Admin
"how it should have been written"
What's wrong with just adjusting the FPU rounding mode?
The rounding isn't done by Delphi, it's done by the CPU, just tell it which rounding mode you want (Set8087CW)
Admin
"This is why we can't have nice things," Getrude said, pointing to the rounding method.
PaulM agreed. "This is not how it is done in The Book of Five Rings". He produced his battered old copy and started to flip to the relevant page.
"The book of Void: Mathematically-Rounding-in-Delphi" he read aloud. "This technique allows you to mathematically round floating-oint numbers in Delphi. But be aware! You must train frequently to achieve the most force of the method!"
PaulM drew his Ultrabook and let his fingers fly deftly over the surface.
"There," he said. "Fixed it. Fancy a beer?"
"You are my hero!" said Getrude.
To be continued...
Admin
Admin
Admin
The new version is of course much better, though I would prefer to avoid almost duplicate code using one additional variable.
Admin
Admin
Curiously, that's how "Banker's rounding" is defined, but not what banks (especially European banks) do: The rule that they should follow is that 0.5 is rounded up.
Admin
You've left the 4 exact duplicate copies of power(10, Decimals) intact. Is it only "almost duplicate" code that you don't like?
Admin
Admin
Admin
Ah, "clever". Far superior to
Admin
Admin
Cleanup for readability:
Problems:
Admin
... which will crash when Value = 0.
Admin
Admin
Admin
would fix that, wouldn't it?
(I haven't done Delphi in ages, it was still called Borland Pascal in those days...)
Admin
And just generally: Bankers rounding might be the way to go for money related math. However if you work in other areas, it's nearly always plain wrong:
Round(11.5) - Round(10.5) = 2 Round(12.0) - Round(11.0) = 1 Round(12.5) - Round(11.5) = 0
So if you have two values that have a fix distance of exactly 1, due to inconsistent rounding you get anything between 0 and 2.
Example: You work with graphics and draw a rectangle from 10.5 to 20.5. Rounded to pixel values you get a 10-pixel wide rectangle.
If you move the rectangle by 1 pixel (11.5 to 21.5) your rectangle is suddenly 12 pixels wide. If you have a repetitive pattern to display, this is VERY visible...
(Yes, this is a generic issue in most modern programming languages where every value seems to be money related...) (Yes, I know that it can be switched off... But only global for the whole application)
Admin
Excel's spreadsheet functions use banker's rounding.
Excel's VBA functions use mathematical rounding.
Good luck with getting around that one...
Admin
It's a good idea for rounding the last bit in floating-point arithmetic: It means that the last bit is zero more often, and when you add two numbers of equal magnitude where both have the last bit equal to zero, the sum will more often have no rounding error at all.
When rounding integer values, you are right, you have to figure out what you actually want to achieve by rounding. For rectangles, it's tricky. Take a few rectangles with integer coordinates that fit together exactly (for example a larger rectangle split into 2 x 5 sub rectangles). Now scale everything by a factor of 1.6 and round, and make sure that all rectangles still fit exactly together, and all have the same size. Impossible.
Admin
Admin
Banker's rounding is designed to minimize the difference between round( sum(x_1..x_n) ) and sum( round(x_1) ... round(x_n) ), in essence, if you have a thousand small payments then the rounding shouldn't make a big difference to the total.
Always rounding up or down (or away from zero / towards zero) will cause the rounding error to accumulate, this usually won't.
Admin
(*) This is a stock phrase. I think in this case, it's just a small country's worth of hurt, not a whole world, but circumstances may alter that.
And you're wrong in your example, because bround(11.5) == 12 and bround(21.5) ==> 22. 22-12 = 10. The problem arises when you have 10.5 and 21.5. brounding those numbers gives 10 and 22, difference 12. Add 1 and then bround, 11.5=>12, 22.5=>22, difference 10. (Note: I'm not saying the concept is wrong, just the specific numbers.)
Admin
Admin
Rounding ties away from zero is exactly as arbitrary as rounding them to even or any other tie-breaking method. Each has its pros and cons.
Admin
Round(11.5 - 10.5) = 1 Round(12.0 - 11.0) = 1 Round(12.5 - 11.5) = 1
Admin
Sorry, I don't buy this. it's too well written to be a real Hanzo story.
Admin
Now, while "1 - 2 * Integer(Value < 0)" might be clever, it's not the most readable. Remind me again why (most) Pascal programmers dislike the conditional operator. "Value > 0 ? 0.5 : -0.5" seems much clearer and avoids another multiplication (whatever the exact syntax, and whether or not you keep the temp variable or put it in the main expression).
Admin
Admin
Admin
Admin
We don't have it in Delphi; pretty much everyone else I know working in it wrote their own.
Admin
Admin
Ah... I haven't worked with Delphi since Delphi 7; I wasn't aware it was added.
Admin
Ah... I haven't worked with Delphi since 7; I wasn't aware it was added.
(Trying again, the first time the response just didn't show up.)
Admin
Admin
I've never been taught rounding other than 'Add 0.5 and then truncate to the integer part.'
That's clean and simple, and never leaves room for ambiguity.
Admin
So you would round -12.4 to -11.
-12.4 + 0.5 = -11.9. Truncated to integer part = -11.