Some suggestions for the use of types
Types are a good thing, if you don't know this then get a job
as a VB programmer and don't bother reading on. If you do realise that
using different types is a good idea then here's a few things you can avoid.
Floats: never use a float for storing an amount of money. I am always amazed
when I hear about someone using floats for storing monetary values and
then being surprised that it loses track of the cents when large amounts
of money are involved. Sure you might think that you can use a "double",
but just think about the accuracy slowly decreasing as you perform calculations...
Also if you use floats you can give up on the idea of doing memcmp() comparisons
of structures as an operation of the form 1 + 3 will not necessarily equal 2 + 2!
I've written a float test program to show the limits of the
accuracy of floats. Here's a summary of it's output when compiled with GCC
2.95.1 on Linux:
last integral million float = 16000001.000000
last integral float = 16777216.000000
last integral billion double = 9007199000000001.000000
last integral million double = 9007199254000001.000000
last integral double = 9007199254740992.000000
This shows us that basic addition and subtraction operations will return the
results you would want until values of 2^24 for float's and 2^53 for double's.
The value of 2^24 cents is less than a typical house, so this is obviously no
use for managing money. 2^53 cents should be enough to represent the sum of
all client funds managed by any bank, so this should do for these operations.
Of course if you want to store every total accurate to .00001 of a cent (as at
least one bank I know of apparently does) then your limit drops to about a
billion dollars again which probably isn't enough.
Yes, double should do for most financial maths as long as you don't need it to
be too precise.
When writing this little test program I initially made a very common mistake
and passed float types to the printf() when using %f. printf() is designed for
taking double types not float types. This stuffed up my initial results
considerably. Also when writing a program of this nature the correct thing to
do is to use some sort of binary search not loop through all possible values.
Macros: as a general rule you don't want to use a macro for the name of
a type. Sure there can be good reasons for doing this (although nothing
springs to mind). But what you don't want to do is get into the situation
where you have a dozen functions and each one does "#define MYTYPE SOME_REAL_TIME"
as that makes things really bad when you get a new programmer into the
project who tries to understand the code - also you can forget about using
Rational Rose or similar tools.
One particular obscenity I saw was some code that passed a pointer to a
type around. One module of the code didn't need to know about the data
that was being pointed to, so it did something similar to the following:
#define TYPE void
typedef TYPE *PTYPE;
Given that they weren't using C++ the best that they could have done
would probably be:
typedef struct STYPE TYPE;
typedef TYPE *PTYPE;
Which is quite a lot better as it still preserves the fact that the
type is somehow different to every other (void *) you're likely to be using.
Type safety and how to really stuff it up.
I once witnessed a programmer who had several different types of data that
he wanted to store in his C++ class - he only wanted to store a single
item of one of those types. A typical programmer might just have allocated
a float member, an int member, etc, or they might have just used a union.
However he apparently decided that the SPARC server he was using didn't
have enough memory and that he should conserve it by doubling up (and did
it in the worst way possible). So he used a "long long" type as he figured
that it was big enough to just stuff any other type into. I believe that
the amount of code generated by the compiler to perform all this type conversion
would probably exceed the 12 bytes of data he may have saved.
If you want to write code like this then use VB. VB has a type called "variant"
that was developed just for you.
Copyright © 1998 Russell
Coker, may be distributed freely.