Re: Comparison issue

2012-03-20 Thread Ali Çehreli

On 03/20/2012 02:08 AM, Don Clugston wrote:

> For starters, note that ANY integer expression which is exact, is also
> exact in floating point.

With the note that the integer type has better precision at higher 
values. For example, there are many 32-bit values that uint can, but 
float cannot represent.


Ali



Re: Comparison issue

2012-03-20 Thread Don Clugston

On 19/03/12 15:45, H. S. Teoh wrote:

On Mon, Mar 19, 2012 at 08:50:02AM -0400, bearophile wrote:

James Miller:


 writeln(v1 == 1); //false
 writeln(v1 == 1.0); //false
 writeln(v1 == 1.0f); //false
 writeln(v1+1 == 2.0f); //true





Maybe I'd like to deprecate and then statically forbid the use of ==
among floating point values, and replace it with a library-defined
function.

[...]

I agree. Using == for any floating point values is pretty much never
right. Either we should change the definition of == for floats to use
abs(y-x)

No, no, no. That's nonsense.

For starters, note that ANY integer expression which is exact, is also 
exact in floating point.

Another important case is that
if (f == 0)
is nearly always correct.


> Using == to compare floating point values is wrong. Due to the nature of
> floating point computation, there's always a possibility of roundoff
> error. Therefore, the correct way to compare floats is:
>
>immutable real epsilon = 1.0e-12; // adjustable accuracy here
>if (abs(y-x)<  epsilon) {
>// approximately equal
>} else {
>// not equal
>}

And this is wrong, if y and x are both small, or both large. Your 
epsilon value is arbitrary.

Absolute tolerance works for few functions like sin(), but not in general.

See std.math.feqrel for a method which gives tolerance in terms of 
roundoff error, which is nearly always what you want.


To summarize:

For scientific/mathematical programming:
* Usually you want relative tolerance
* Sometimes you want exact equality.
* Occasionally you want absolute tolerance

But it depends on your application. For graphics programming you 
probably want absolute tolerance in most cases.


Re: Comparison issue

2012-03-19 Thread H. S. Teoh
On Mon, Mar 19, 2012 at 08:50:02AM -0400, bearophile wrote:
> James Miller:
> 
> > writeln(v1 == 1); //false
> > writeln(v1 == 1.0); //false
> > writeln(v1 == 1.0f); //false
> > writeln(v1+1 == 2.0f); //true

Using == to compare floating point values is wrong. Due to the nature of
floating point computation, there's always a possibility of roundoff
error. Therefore, the correct way to compare floats is:

immutable real epsilon = 1.0e-12; // adjustable accuracy here
if (abs(y-x) < epsilon) {
// approximately equal
} else {
// not equal
}


> Maybe I'd like to deprecate and then statically forbid the use of ==
> among floating point values, and replace it with a library-defined
> function.
[...]

I agree. Using == for any floating point values is pretty much never
right. Either we should change the definition of == for floats to use
abs(y-x)

Re: Comparison issue

2012-03-19 Thread Jesse Phillips

On Monday, 19 March 2012 at 12:50:02 UTC, bearophile wrote:

James Miller:


writeln(v1 == 1); //false
writeln(v1 == 1.0); //false
writeln(v1 == 1.0f); //false
writeln(v1+1 == 2.0f); //true


Maybe I'd like to deprecate and then statically forbid the use 
of == among floating point values, and replace it with a 
library-defined function.


Bye,
bearophile


I feel I should expand on bearophile's statement here. Checking 
for equality in a float is usually wrong. After performing 
operations on a float the accuracy if the number changes. So 
performing any operations could result in your result being off 
by a fraction


I.e. v1 could be (I'm not being acurate here as to what it, print 
it out and see)

1.01
0.87

I think there is a std.math function called frequal or something.


Re: Comparison issue

2012-03-19 Thread James Miller
On Mar 20, 2012 1:50 AM, "bearophile"  wrote:
>
> James Miller:
>
> > writeln(v1 == 1); //false
> > writeln(v1 == 1.0); //false
> > writeln(v1 == 1.0f); //false
> > writeln(v1+1 == 2.0f); //true
>
> Maybe I'd like to deprecate and then statically forbid the use of ==
among floating point values, and replace it with a library-defined function.
>
> Bye,
> bearophile

I wouldn't mind if it was just type weirdness, but its not. It appears that
1 does not equal 1.


Re: Comparison issue

2012-03-19 Thread bearophile
James Miller:

> writeln(v1 == 1); //false
> writeln(v1 == 1.0); //false
> writeln(v1 == 1.0f); //false
> writeln(v1+1 == 2.0f); //true

Maybe I'd like to deprecate and then statically forbid the use of == among 
floating point values, and replace it with a library-defined function.

Bye,
bearophile


Comparison issue

2012-03-19 Thread James Miller
Hey, I'm trying to do some vector based code, and my unittests started
to fail on testing normalize. I'm using the standard algorithm, but
the assert is always return false. I did some investigation, and can
show that this program causes failure:


import std.math : sqrt;
import std.stdio : writeln;

T size(T)(T[] t){
T val = 0;
for(size_t i = 0; i < t.length; i++) {
val += t[i]*t[i];
}

return sqrt(val);
}

void normalize(T)(ref T[] t) {
auto s = size(t);
foreach(ref v; t) {
v /= s;
}
}

void main() {
float[] vector = [1,2,3,4];
normalize(vector);
auto v1 = size!float(vector);

writeln(v1 == 1); //false
writeln(v1 == 1.0); //false
writeln(v1 == 1.0f); //false
writeln(v1+1 == 2.0f); //true
}

I used typeid and can show that the type of `v1` is `float`, as you'd
expect. And the last one passes fine, as does doing `(v1+1)-1 == 1`.
I'm not sure what could be causing this. I believe it may be a bug,
but I would like to see if I'm just wrong instead.

--
James Miller