We recently solved a problem of Daniel with a rather simple computation error in thread184-1738661.
Such calculation errors pop up from time to time and are not a CPU error or VFP bug, it's simply the limitation of floating point arithmetic. I get to the general overview of that later, but you may read an introduction to the problems in Python documentation Floating Point Arithmetic: Issues and Limitation, which shows the general problem is language independent.
Daniel wanted a value truncated at 6 decimal places. The basic computation is x=a/b and to get the truncation of that simple division he used FLOOR(1000000*a/b)/1000000, because FLOOR() like INT() truncates all decimal places, you first shift the number 6 decimal places to the left, then truncate decimal places of that number (which would have been 7th and higher decimal place before the shift) and then shift back 6 places to the right. So you expect 6 decimal places, not rounded up by the 7th decimal place, simply truncated.
That failed with the rather harmless looking example of computing 265.96/20. If you SET DECIMALS TO 6 and let VFP execute ? 265.96/20 you get the correct and precise result of 13.298000. Using Floor(1000000*265.96/20)/1000000 you get 13.297999
Mike Lewis solved that by using ROUND() in a way, which truncates a number to a certain precision instead of rounding it. ROUND has the advantage of having built in the computation to a certain precision and we only need to "tame" it to truncate instead of round. The trick is to subtract the rounding offset of 5 at the next decimal place. In case of 6 decimal places that's ROUND(x - 0.0000005), 6) for positive x, and ROUND(x + 0.0000005), 6) for negative x, or ROUND(x - SIGN(x) * 0.0000005), 6) in general. Round(265.96/20-0.0000005,6) is 13.298000, problem solved.
We can generalize this as a TRNUCATE() function, if you like:
Later on I'd like to put this new function to the test and discuss other proposed solutions and why they work, too or fail. For now my time is up, though.
Bye, Olaf.
Such calculation errors pop up from time to time and are not a CPU error or VFP bug, it's simply the limitation of floating point arithmetic. I get to the general overview of that later, but you may read an introduction to the problems in Python documentation Floating Point Arithmetic: Issues and Limitation, which shows the general problem is language independent.
Daniel wanted a value truncated at 6 decimal places. The basic computation is x=a/b and to get the truncation of that simple division he used FLOOR(1000000*a/b)/1000000, because FLOOR() like INT() truncates all decimal places, you first shift the number 6 decimal places to the left, then truncate decimal places of that number (which would have been 7th and higher decimal place before the shift) and then shift back 6 places to the right. So you expect 6 decimal places, not rounded up by the 7th decimal place, simply truncated.
That failed with the rather harmless looking example of computing 265.96/20. If you SET DECIMALS TO 6 and let VFP execute ? 265.96/20 you get the correct and precise result of 13.298000. Using Floor(1000000*265.96/20)/1000000 you get 13.297999
Mike Lewis solved that by using ROUND() in a way, which truncates a number to a certain precision instead of rounding it. ROUND has the advantage of having built in the computation to a certain precision and we only need to "tame" it to truncate instead of round. The trick is to subtract the rounding offset of 5 at the next decimal place. In case of 6 decimal places that's ROUND(x - 0.0000005), 6) for positive x, and ROUND(x + 0.0000005), 6) for negative x, or ROUND(x - SIGN(x) * 0.0000005), 6) in general. Round(265.96/20-0.0000005,6) is 13.298000, problem solved.
We can generalize this as a TRNUCATE() function, if you like:
Code:
FUNCTION Truncate()
Lparameters tnNumber, tnPrecision
Return Round(tnNumber-0.5*Sign(tnNumber)*10^-tnPrecision,tnPrecision)
ENDFUNC
Later on I'd like to put this new function to the test and discuss other proposed solutions and why they work, too or fail. For now my time is up, though.
Bye, Olaf.