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)
|