float equality

Don nospam at nospam.com
Mon Feb 21 06:27:18 PST 2011


spir wrote:
> On 02/21/2011 05:32 AM, Walter Bright wrote:
>> Kevin Bealer wrote:
>>> == Quote from Walter Bright (newshound2 at digitalmars.com)'s article
>>>> Kevin Bealer wrote:
>>>>> You could switch to this:
>>>>>
>>>>> struct {
>>>>> BigInt numerator;
>>>>> BigInt denominator;
>>>>> };
>>>>>
>>>>> Bingo -- no compromise.
>>>> It cannot represent irrational numbers accurately.
>>>
>>> True but I did mention this a few lines later.
>>
>> I guess I'm not seeing the point of representing numbers as ratios. 
>> That works
>> only if you stick to arithmetic. As soon as you do logs, trig 
>> functions, roots,
>> pi, etc., you're back to square one.
> 
> "Naturally" non-representable numbers (irrationals), or results of 
> "naturally" approximate operations (like trig), are not an issue because 
> they are expected to yield inaccuracy.

You keep talking about "inaccuracy" and "approximation", when I think 
you really mean "rounding".

Actually irrationals are a *big* issue. You might expect sin(PI) == 0, 
but it isn't. This isn't a problem with sin(), it's a problem with the 
limited resolution of PI.  sin(3.141592654) != 0.

> 
> This is different from numbers which are well definite in base ten, as 
> well as results of operations which should yield well definite results. 
> We think in base ten, thus for us 1.1 is exact. Two operations yielding 
> 1.1 (including plain conversion to binary of the literal '1.1') may in 
> fact yield unequal numbers at the binary level; this is a trap, and just 
> wrong:
>     assert (1.1 != 3.3 - 2.2);    // pass
> Subsequent issue is (as I just discovered) that there is no remedy for 
> that, since there is no way to know, in the general case, how many 
> common magnitude bits are supposed to be shared by the numbers to be 
> compared, when the results are supposed to be correct. (Is this worse if 
> floating point format since the scale factor is variable?)

Decimal floating point formats exist, and have been implemented in 
hardware in some cases. They don't suffer from the rounding-during-I/O 
issue that you mention. Fortunately D supports the %a binary floating 
point format, eg, 0x1.34p+46, which gives you what-you-see-is-what-you-get.

> 
> This lets me think that, for common use, fixed point with a single 
> /decimal/ scale factor (for instance 10^-6) may be a better solution. 
> While the underlying integer type may well be binary --this is 
> orthogonal-- we don't need using eg BCD. Using longs, this example would 
> allow representing numbers up to +/- (2^63)/(10^-9), equivalent to 
> having about 43 bits for the integral part (*), together with a 
> precision of 6 decimal digits for the fractional part. Seems correct for 
> common use cases, I guess.
> 
> 
> Denis
> 
> (*) 10^6 ~ 2^20
> (2^63)/(10^-6) > 9_000_000_000_000


More information about the Digitalmars-d mailing list