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.

  1. 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.
  2. 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:
    struct STYPE;
    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.

  3. 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.