On 30-Oct-04 Graham wrote:
On Saturday 30 October 2004 13:59, Tim Green wrote:
float l = 45.4567; float d = floorf(l); std::cout << "l-d = " << l - d << std::endl;
Basically, I getting an odd value printed for l - d (it comes out as 0.456699 and not 0.4567 as expected).
"float" is not that acurate. You might have more luck with "double".
Good luck! Tim.
Neither float nor double can truly represent some numbers. Just as 1/3 or 1/7 cannot be expressed exactly in decimal, some numbers
- e.g. 0.1 - do not have an exact binary representation. Hence
the tendency for the result to come back as a recurring decimal.
Very true!
Your numbers should never have gone to binary in the first place.
Contentious!
[...] Interestingly (to me at least), in the days when we programmed everything in assembler, 8-bit microprocessors had a set of BCD (Binary Coded Decimal) instructions that allowed computations to mirror what we expect in real life. They were put there for use by pocket calculators, which is why these machines give the *right* answers and recur a third rather than a tenth. I expect the instructions are still there, but I doubt a C compiler makes use of them.
Which just goes to show that what you gain on the swings you lose on the roundabouts.
The majority of numerical programs work to a fixed precision in one base or another. Fortran (and C and C++ ... and most numerical software which depends on their in-built arithmetic) work to a finite number of binary digits (depending on the type of the variable). However, you could program a BCD calculator in C, though you would not be directly using the math library routines.
As pointed out, 0.1 does not have an exact binary representation to any number of digits. So things get a bit ragged with several decimal places. On the other hand, any inverse power of 2 (1/2^k) is exactly stored so long as k does not exceed the length of the mantissa (in bits) in the number storage. Because 2 is prime, the only division that can give an exact result is division by 2.
The BCD representation is exact for decimal fractions 1/10^k so long as k does not exceed the number of 4-bit blocks available in number storage. Because 10 has factors 2 and 5, divisions by 2 and 5 can give exact results.
In both cases, divisions by other numbers (1/3, 1/7, 1/9) will always give inexact results.
There are, however, programs which can allow you an arbitrary degree of precision. One such (and it should be on any Linux system) is the program 'bc' (an early version of which was included as a C coding example in Kernighan and Ritchie's book):
"man bc" -> bc(1) NAME bc - An arbitrary precision calculator language
It is quite fully programmable (loops, conditionals and stuff), so if you really want to break out of the limited precision of standard language it is worth considering. However, it has only a very limited repertoire of mathematical functions.
Example (pi to 1000 decimal places; note that the "atan" function a() is the only way to tell bc about pi):
$ bc -l bc 1.06 Copyright 1991-1994, 1997, 1998, 2000 Free Software Foundation, Inc. This is free software with ABSOLUTELY NO WARRANTY. For details type `warranty'. scale=1000 pi=4*a(1) print pi 3.141592653589793238462643383279502884197169399375105820974944592307\ 81640628620899862803482534211706798214808651328230664709384460955058\ 22317253594081284811174502841027019385211055596446229489549303819644\ 28810975665933446128475648233786783165271201909145648566923460348610\ 45432664821339360726024914127372458700660631558817488152092096282925\ 40917153643678925903600113305305488204665213841469519415116094330572\ 70365759591953092186117381932611793105118548074462379962749567351885\ 75272489122793818301194912983367336244065664308602139494639522473719\ 07021798609437027705392171762931767523846748184676694051320005681271\ 45263560827785771342757789609173637178721468440901224953430146549585\ 37105079227968925892354201995611212902196086403441815981362977477130\ 99605187072113499999983729780499510597317328160963185950244594553469\ 08302642522308253344685035261931188171010003137838752886587533208381\ 42061717766914730359825349042875546873115956286388235378759375195778\ 18577805321712268066130019278766111959092164201988 quit $
Ted.
-------------------------------------------------------------------- E-Mail: (Ted Harding) Ted.Harding@nessie.mcc.ac.uk Fax-to-email: +44 (0)870 094 0861 [NB: New number!] Date: 30-Oct-04 Time: 15:11:06 ------------------------------ XFMail ------------------------------