storing dollar amounts in integers.

Jan 09, 2008 17:36

i've been doing the accounting for sunflower river, so i've been playing with little programs and code to help me with that. as is often the case, i'm frustrated with floating point numbers on computers. i really need to represent dollars, and the imprecision of doing so with floating point is causing me grief. so i've been working on storing ( Read more... )

hacking, sunflower river

Leave a comment

Comments 19

gwillen January 10 2008, 01:43:21 UTC
Two comments so far: 1) it makes no sense to multiply dollars by dollars. ;-) And if you're multiplying dollars by an integer, of course, you don't need the scaling factor. 2) The way your div is currently defined, it's dollars/dollars -> integer. If you want the result to be in fixed-point dollars, you have to multiply by 100, symmetric with your definition of multiplication...

Reply

aisa0 January 10 2008, 16:30:10 UTC
i realized the problem with div riding home last night, but you point 1 is very well taken!

it turns out that i will have to do division eventually, once, in the application. but it is to divide dollars by people, so my definition works, it's just defined poorly.

thank you!

Reply


two_pi_r January 10 2008, 02:04:10 UTC
Your C blows my mind with all the bizarre idioms. Then again, my Ruby isn't any less weird.

Reply


two_pi_r January 10 2008, 02:24:10 UTC
Also, as an actually-somewhat-useful suggestion, I read somewhere that when inserting commas, the algorithm is more elegant to do from the right-hand-side instead of starting at the left. I think it was a regular expression guide, though. So maybe it's not so useful. Damn.

Reply


tonberrygrrl January 10 2008, 03:02:01 UTC
I'm sorry babydoll, that's really painful. One-letter variables hurt my brain, as does having hacks just for the sake of having hacks.

I'm guessing that sprintf() would be unsuitable for your purposes...?

size_t
fmt_usd(char *b, usd m)
{
int dollars;
int cents;

dollars = m / 100;
if( m < 0 ) m = -m;
cents = m % 100;

sprintf( b, "%d.%02d", dollars, cents );
}

Also, would scan_usd( "12345678901234567890", &m ); give, ahm, interesting results? Even if you might not often see dollar amounts bigger than ~$2M, would it hurt to check your integer size boundaries? I didn't notice any integer size boundary checks, anyway.

Reply

aisa0 January 10 2008, 18:48:06 UTC
so, my program is still being tested, and i had to make a fix while running these reports (which is to say, i'm not running the code i posted here, i had to fix a bug.), the big reason not to use sprintf is that it is an interpreted language. the runtime doesn't compile "%d.%02d" and generate a use-specific sprintf. instead it interprets that string each time it is called.

number conversion is a fairly low-level detail. it gets called a lot during routine use, and can easily be the bottleneck when processing data. optimizing some of these routines was a small part of my job at prediction company, where we dealt with hundreds of megs of data every day, and displayed stuff out of a multi-terabyte database. you really noticed slowdowns if your number conversion routines weren't fast.

running your code, i get the following times for (INT_MIN-1)/100 ... INT_MAX/100:

2m18.91s real 2m13.96s user 0m0.01s system

running my code, i get the following times for the same range:

0m8.03s real 0m7.75s user 0m0.00s systemmore ( ... )

Reply

tonberrygrrl January 10 2008, 20:55:07 UTC
You know if you're really looking for speed, you could just write your conversion routines in assembly language. After all, if you're using features that are undefined in the C language, you're certainly not aiming for portability! *raspberries* =)

But in all honesty, do you really feel that sprintf() is too slow for your needs here? When you claimed that you needed the speed you cited your work at the prediction company, but accounting for Sunflower River does NOT involve dealing with hundreds of megs of data every day, nor does it involve displaying stuff out of a multi-terabyte database.

Odd, i did the same side-by-side comparison of your code vs. mine on my desktop compy. I compiled them both with "gcc -O3 -funroll-loops foo.c", and when i timed them, here's what i got:

YOURS:
real 0m4.952s
user 0m4.892s
sys 0m0.032s

MINE:
real 0m19.399s
user 0m18.765s
sys 0m0.096s
Your code is faster, but i clearly do not get the 15x speed increase that you do.

*giggle* You're just proud of your code, aren't you? =)

Reply

ravendisplayed January 10 2008, 21:12:24 UTC
the runtime doesn't compile "%d.%02d" and generate a use-specific sprintf. instead it interprets that string each time it is called.

I had never thought about that before, now that I have it is going on my big list of things that need to be redone in the codebase that I have inherited.

Reply


samiraalthores January 10 2008, 03:03:33 UTC
teh codes! teh codes!

I think I just had a PTSD episode leftover from grad school.

Reply

aisa0 January 10 2008, 16:12:29 UTC
ack! i should have warning! ^_^

i do post code from time to time, as it's a fair part of my day job, and i like talking about it; whether i'm posting it or someone else is.

i forget sometimes that people actually have been traumatized by their experience programming. i tend to lump people into two groups, people who understand the code and can talk about it and people that just don't care and will therefor skip the entry.

i should know better, as i know enough people in person that shudder at the thought of programming!

Reply


Leave a comment

Up