- 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
Cents doesn't means cents...
Makes cents I suppose. rimshot
Admin
But what if management later decides that price-in-cents, subsequently price-in-tenths-of-cents, subsequently price-in-hundreths-of-cents should now be price-in-roman-numerals?
Admin
Long ago - so long that it's probably safe to mention it, as there's no chance anyone will ever ask me to code in it - I wrote RPG programs (Report Program Generator, for you kiddies).
Now, as you'd imagine, RPG is good at generating reports, specifically on line printers. It knows what line it's on, how far it is to the end of the page, all sorts of wonderful things. If you want the subtotal 5 lines from the bottom, that's one line of code.
A previous programmer did not get this. He thought in Cobol and he wrote in Cobol, even when using RPG. He wrote his own line count routines. He wrote his own page count routines. Something that should have been 10 lines of code (in a language where something with 20 lines of code was a seriously complex operation) turned into 10 pages (heaven forbid he use the include functionality to reuse his page counters). And of course his code had bugs, and those bugs were buried in all the cruft.
My boss could not understand why I'd rewrite any program of his that I had to work on. Wouldn't it just be faster to find the bug? But then, my boss was only in the software business because back when he'd owned an office products supply company, he'd noticed that before selling a 5 cent pencil you had to buy a 4 cent pencil, but before selling a $10K piece of software you only needed to buy a $5 floppy.
Admin
Any class that takes currency as a floating point value is a wtf in itself quite apart from the changing database value.
Admin
So not only do we have a complete logic WTF by pete, we also have a bit of a technical one. A decimal / int / float in .net is a 'primitive' and can live it's merry life on the statck.
However Money myMoney = new Money(0.10); // $.10, is creating new object, of type 'Money' which lives its not so happy life on the managed heap, just sitting their waiting to be cleaned up. I'm guessing in a financial system, there is a hell of a lot of 'Money' that needs to be manipulated in code.
Work that Garbage Collector!
Admin
Well, the idea isn't so bad. Save a number with the precision you need in a simple integer field. The problem is, there is implied information (level of precision) that wasn't captured in the database.
Old school game programmers will recognize this as a "fixed point" technique; representing floats as integers, so you might have 16.16 (16 bits for the integer part, 16 bits for the floating point part). Really handy back when floating point units weren't quite as fast and DOOM ran without a 3D card!
He should have had his class spit out another column that documented the precision. Or, just used the MONEY type provided by SQL. :-)
Admin
I guess management is fond of throwing good price_in_cents after bad.
Blessed are those techies that are managed by former techies.
Admin
Millions for nonsense, but not one cent for entropy.
Admin
Well... Sql Money and .net decimal are actually stored as 3 integers, and works for arguments sake in the way you mention... So yes, not such a bad idea over using floats; but this has just been implemented with a complete lack of knowledge that Sql Money and decimal exist in Sql and .net respectively, as well as being implemented incorrectly. If this is MSSQL it’s quite hard to miss the money type when using the inbuilt WYSWIG table designer… you would think Pete would have seen it and enquired a bit further as to what it did before trying to reinvent the wheel… badly.
Pete also strikes me as someone who thought ‘databases are just where I shove data’, as without the application code there is no way to interpret the real meaning of the data in the cents column.
Sigh
Admin
This presumes that a manager who is a former techie: a) was good at being a techie. b) isn't set on having everything work the way it did in 1975.
Admin
i like an ending like this. it's the feel-good wtf of the week.
Admin
Doesn't it seem obvious to anyone else here that Andy is unfamiliar with futures trading and commission structures, and has an inferiority complex about his own code? It seems like he is publicly lambasting Pete in order to try to cover his own hide. So he should have looked at the code in the money class a long time ago before monkeying around with Pete's code trying to "fix" things. Then maybe he wouldn't be in such a mess.
Admin
If this is C#, we aren't shown the class definition, so it may be a struct rather than a class. If "Money" was a struct, it would still live on the stack.
Admin
Were alex working in MySQL 4.1, this would have been a horrible mistake. All operations on MySQL's DECIMAL (arbitrary precision) type are done with float operators. So you'll have all the standard floating point errors.
For databases without arbitrary precision math, storing currency in an integer is the right choice.
Admin
gah.
why do people think they know better? walked into a module a while's back where the developer had stripped all dates of //'s, done a bit of jiggery pokery and lobbed his own date-format into the db. ported the project to servers in europe and lost all the content. go locale, go.
Admin
Pete? Is that you?
It has to be.
Admin
No, it is not me
Admin
That's a neat perf trick of "representing floats as integers".
Just one question how does one represent the float value 1 X 2e16 in the "fixed point" you describe? Or 1 X 2e-16? I got an idea. Use some of the bits for the matissa and some for the exponent. I think I'll call it a gliding point.
Admin
Actually, I'm pretty sure the C# compiler performs escape-analysis (I think that's what it's called). Basically, if an object's reference leaves a function, it is allocated on the heap. Otherwise, it is allocated on the stack.
Of course, declaring Money as a struct guarantees it's always allocated on the stack.
Admin
My first thought, too. :)
Admin
sniffs and wrinkles his nose
That comment really has a bad cent!
Admin
Admin
Admin
That technique can still be used in multiplayer games to store values that need to stay exactly in sync across different platforms.
Admin
Admin
From the way this started, I thought this was going to be from somebody at my company, but the identifier price_in_cents made me realize that's not the case. Here it would have been more to the tune of pr_cnt. way more human readable.
Admin
I wouldn't have even gone to a decimal.. just store everything in cents. Best design is always store the lowest possible unit.
You don't need dollars just cents. How many dollars can be calculated based on the amount of cents.
I do the same for time.. why store hours and fraction of hours.. or minutes and fraction of minutes... when you can store seconds and convert to get either?
Admin
And it's cold. Quite schilling, in fact. A bit heavy too. At least fifty pounds.
Admin
And it's cold. Quite schilling, in fact. A bit heavy too. At least fifty pounds.
Admin
Maybe things will change.
Admin
Admin
At least it was easy to fix. All you need to do is hire a consultant to add some XML.
Admin
What's the expression?
"XML is like violence. If it doesn't solve your problem, use more."
Admin
Admin
All of you go to your rooms! Bad! Bad puns! Shoo!
Admin
At least it would be binary.
Captcha: Gold-Pressed Latinum
Admin
Yes, you may well laugh now. But when beings from a superior civilization on another planet come 175,000 light-years to bank their money with us, and happen to use base 12, and are VERY particular about roundoff errors, and have great big honkin' scrotum-shrivelin' death ray cannons, then we'll see, hah.
-Harrow.
Admin
Good point, for some reason I just assumed it was part of a class definition ...
Admin
One does not, just as one does not represent 2^32 in a 32-bit integer.
Admin
Of course the exponent, mantissa, and radix should be stored in an Xml file, and we need some Factories, Messages, and Commands... Perhaps a Controller as well, and some class with the word 'strategy ' in, I like strategy
Admin
How often does a company sell something that costs 10 quadrillion dollar?
Admin
actually the CRL allocates all reference types (with a few exceptions like stackalloc'ed non-reference type arrays) on the heap and non-reference types (including structs) on the stack (as long as they are not boxed) or inside reference types on the heap
Admin
Being from the UK; I think that pound for pound, it seems like a Sterling solution to the problem. ;)
Admin
Price in Nonsense
What a great title!
Admin
So that's how this happened!
http://www.24.com/news/?p=worlda&i=789135
Admin
His solution will lead to a future WTF. Don't use floating point for money.
Admin
Admin
http://www.ibm.com/developerworks/java/library/j-jtp09275.html
Ahh, here's where I read about escape analysis. I guess I confused the Java runtime with the .NET CLR on this issue. Although, I'm surprised that MS didn't duplicate this technique, seeing as how much from Java they did rip off.
Admin
Thanks... I was also going to post this. It is completely ludicrous to use floating point types for currency, be it in the database or in the code.
In Europe it is quite simple: Since the adoption of the Euro it is compulsory to perform currency calculations with 4 decimal places.
So, best bet is using an integer type and treat all values as ten thousandths of a Euro. Placing the decimal point is only necessary for user interaction and is moreover trivial.
If different currencies are required, the currency information has to be kept anyway, thus precision information can be stored as well.
Of course in that case an extra table is necessary for the currency info by all means. Otherwise we'd have to expect solutions where two additional fields (currency and precision) have to be added to each table requiring monetary values... normalization, anyone? ;o)
Pete's solution was not so bad per se, he just was not able to anticipate future requirements and create a model capable of such changes.
BTW, it would have been quite trivial to update the data after each precision change.
An interesting question is - was Pete really that incompetent, or just sloppy? Perhaps he used an integer because he did not know of the DECIMAL-type ;o) But then, he wrote a convenience class to convert decimal monetary values (which are dumb in the code anyway, but perhaps others insisted on using them) into his database representation... so at least it seems he was aware of the problem to some extent. But as long as the API supports using decimal monetary values in the code, not much is gained - the precision errors inherent to the IEEE 754 standard would be accumulated in the calculations. Storing these increasingly inaccurate values as floats or integers does not make a lot of difference.
Therefore Andy's solution of changing the type to DECIMAL makes matters even worse really, because most probably they did nothing to change the use of floating point arithmetic in the code - they are just asking for inexplicable errors in their monetary calcuations.
It seems that the managment was more competent, because they wouldn't let the changes in the database happen - but more likely this was just by chance, they just didn't like change in general ;o)
Admin
Quake 1 makes use of the same technique. ;) IT also houses a few other interresting tricks.