TIP: Click on subject to list as thread! ANSI
echo: c_echo
to: BOB STOUT
from: GEORGE WHITE
date: 1998-02-26 08:21:00
subject: What`S Happening Here?

Hi Bob,
This is something I didn't expect to be writing to you about!
You wrote to Neil Heller:

BS>  It's all pretty straight forward - just follow the steps.
BS>First, let's review the rules:
BS>1.  The result is a long int, so whatever the result, it will be 
xplicitly
BS>    cast by the assignment. If the result is a floating point value, the 
cas
BS>    will be done by truncation of the fractional part.
BS>2.  Multiplication takes precedence over addition.
BS>3.  Evaluation can occur in any order allowed by precendence, but the type 
o
BS>    the result will depend on the type of the most precise argument.
BS>4.  The result of all floating point operations in ANSI/ISO C is double. 
The
BS>    only advantage of using type float is that it takes up half the 
torage
BS>    space at the expense of accuracy.
????
In "Classic" K&R C all non integral calculations are done as doubles,
but according to the information I've read ANSI C (and C++) will use the
largest non-integral type in the expression - in this case float.

BS>  The key to remembering all this is given in rule #3 above
BS>- the type of any evaluation result will be the type of
BS>the most precise operand (remember, floats are basically
BS>ignored except for storage purposes, and ints are usually
BS>either shorts or longs in disguise). IOW...
For floats true in K&R C but, according to my reading, not true of ANSI,
and the dangers of ints to portability cannot be emphasised too much.
My modified table (differences between K&R and ANSI marked with "<<<"):
                                 K&R      ANSI
BS>        char    char   => char     char
BS>        char    short  => short    short
BS>        char    long   => long     long
BS>        char    float  => double   float  <<<
BS>        char    double => double   double
BS>        short   short  => short    short
BS>        short   long   => long     long
BS>        short   float  => double   float   <<<
BS>        short   double => double   double
BS>        int     long   => long     long
BS>        int     float  => double   float   <<<
BS>        int     double => double   double
BS>        long    long   => long     long
BS>        long    float  => double   float   <<<
BS>        long    double => double   double
BS>        float   float  => double   float   <<<
BS>        float   double => double   double
BS>        double  double => double   double
BS>  A couple of notes and corollaries:
BS>1.  Where your result can overflow, always use explicit casts to make room 
f
BS>    the result. For example:
BS>        short arg1, arg2;               /* Each can be 16 bits          */
BS>        long  result;                   /* Product can be 32 bits       */
BS>        result = (long)arg1 * arg2;     /* Force 32 bit evaluation      */
Worth emphasising, the cast to the result occurs _after_ evaluation.
BS>2.  Avoid type float where possible. Its only value is where your storage
BS>    space is at a premium - typically RAM in tight embedded systems or 
ata
BS>    files on a nearly full disk. OTOH, I work almost exclusively in 
embedded
BS>    systems and I rarely use floats! They're virtually useless in any 
modern
BS>    desktop application. All you accomplish by using them is to accumulate
BS>    inaccuracies at a faster clip.
Fair comment.
BS>3.  The one exception to the above is where the system doesn't suppport
BS>    floating point calculations in hardware. Obviously, 32-bit floats can 
be
BS>    calculated in software faster than 64-bit doubles. But even this can 
e
BS>    misleading, since the compiler and library must be explicitly written 
to
BS>    support 32-bit floating point math. Otherwise, ANSI/ISO is followed 
nd
BS>    everything's still done using doubles, only in software. The default
BS>    operation of most early PC compilers is to still use doubles through 
the
BS>    software x87 emulator libraries.
Can you check this.
BS>4.  While on the topic of imprecision, in your example, did you really 
ean
BS>    *exactly* (0.9999) or perhaps (0.9999...) instead? If the latter, 
ou'd
BS>    have been better off defining something like...
BS>        #include 
BS>        #define ALMOST_ONE (1.0-DBL_EPSILON)
BS>    ...which would've accurately conveyed your intent within the limits of
BS>    your compiler.
BS>5.  Using the "F" suffix is useless, although mostly benign. As noted, all
BS>    internal floating point calculations will be done using doubles 
nyway.
BS>    The one instance where it isn't benign is when using a float results 
n
BS>    loss of precision vis-a-vis using a double. The real pity is that you 
ma
BS>    be throwing away precision uselessly since your compiler will still
BS>    promote the value to a double for calculation purposes.
But, as I said above, I understand ANSI does not mandate this, although
I suspect it is allowable.
George
 * SLMR 2.1a * All Trademarks acknowledged (just in case ).
--- Maximus/2 3.01
---------------
* Origin: DoNoR/2,Woking UK (44-1483-717905) (2:440/4)

SOURCE: echomail via exec-pc

Email questions or comments to sysop@ipingthereforeiam.com
All parts of this website painstakingly hand-crafted in the U.S.A.!
IPTIA BBS/MUD/Terminal/Game Server List, © 2025 IPTIA Consulting™.