comparison error

Blitz3D Forums/Blitz3D Programming/comparison error

impersonalis(Posted 2007) [#1]
Hi!
I would like to knew the reason of the uncorrect working of the statement of comparison in the following test:
Graphics 800,600
SetBuffer BackBuffer()
SetFont LoadFont("MS Sans Serif",20)

Local intervalx#[20]
Local temp0#,temp1#,temp2#,tempc%,b#
x#=14.143

xmax#=15.051

h#=0.242
temp0=13.417
tempc=1
While (temp0<=xmax)
	temp2=temp0+h	
	intervalx[tempc]=temp2
	temp0=temp2
	tempc=tempc+1
Wend

b=intervalx[3]


If  x=b
	Print ""+x+"="+b 
Else
	Print ""+x+"<>"+b 
EndIf



WaitKey()
End

if to insert the next corrections
Graphics 800,600
SetBuffer BackBuffer()
SetFont LoadFont("MS Sans Serif",20)

Local intervalx#[20]
Local temp0#,temp1#,temp2#,tempc%,b#
x#=14.143

xmax#=15.051

h#=0.242
temp0=13.417
tempc=1
While (temp0<=xmax)
	temp2=temp0+h	
	intervalx[tempc]=temp2
	temp0=temp2
	tempc=tempc+1
Wend

b=intervalx[3]
b=Float(Str(b))


If  x=b
	Print ""+x+"="+b 
Else
	Print ""+x+"<>"+b 
EndIf



WaitKey()
End

then everything is working fine.
Ver. 1.98|1.98|1.98


skidracer(Posted 2007) [#2]
You can use integers if you want to do exact comparisons, floating point numbers by their nature will introduce rounding errors in most of the calculations in your test (difficult to see as Blitz3D rounds floats to 7 decimal places when it converts to strings for the purposes of printing etc.).

To use integers, you can use variables that store amounts in units of 1/1000ths, you just need to remember to divide any products by 1000 and insert your own decimal place when printing or use your trick where the string conversion is effectively rounding the inputs before the comparison.

If you have to do equality tests with floats you will need to compar the absolute difference of the two numbers with some sort of epsilon value.


impersonalis(Posted 2007) [#3]
The Idea with checking the module of difference on small size epsilon value is very terrible.
The output code also very crockhood. Can you answer to me on my question? Why two identical numbers are not to each other?
I don't scare the inaccuracy, appearing under bigger calculations and built-in system of truncation.
In this accident - I compare two identical numbers, peacefully be situated in float.


GfK(Posted 2007) [#4]
The Idea with checking the module of difference on small size epsilon value is very terrible.
The output code also very crockhood. Can you answer to me on my question: Why two identical numbers are not to each other?
I don't scare the inaccuracy, appearing under bigger calculations and built-in system of truncation.
In this accident - I compare two identical numbers, peacefully be situated in float.
As skidracer said, don't EVER perform comparisons on two floats and expect them to be identical at any point.

Its not a problem with Blitz. Try it in C, you'll get the same results.

As for the above paragraph, didn't understand a word. Crockhood, indeed... :/


Dreamora(Posted 2007) [#5]
At runtime there are no identical numbers unless both are defined at const, which makes the comparision pointless as you know the result upfront.

If you compare floats, always compare with an epsilon margin within they must be the same or do not use floating point bug fixed point math or something similar.

One thing that will cause further problems if you convert code it, which was mentioned by skid, is that the "old blitz" round the output result, so you don't have full float accuracy. On the other side, this behavior allows float = float checks up to a given point (around .001 - .005 accuracy with "normal" numbers *0 - 1000*)


impersonalis(Posted 2007) [#6]
At first I wrote the programm on C++ ( because I work with it longer, than on B3d), but I rewrote it because of specifics of the further using. If you persist - I tomorrow will check this code on MSVC . P.S.: Excuse me for quality of the remarks - I speak english a little.


Floyd(Posted 2007) [#7]
Blitz3D rounds the displayed values to six digits.
In your example both numbers are rounded to 14.1430 and then final 0 is removed.

So x and b look the same, but in fact x is a little bigger than b.
Here are the same numbers, but now you can see the small difference:

Graphics 800,600
SetBuffer BackBuffer()

Local intervalx#[20]
Local temp0#,temp1#,temp2#,tempc%,b#
x#=14.143

xmax#=15.051

h#=0.242
temp0=13.417
tempc=1
While (temp0<=xmax)
	temp2=temp0+h	
	intervalx[tempc]=temp2
	temp0=temp2
	tempc=tempc+1
Wend

b=intervalx[3]

; Blitz3D makes x and b look the same when displayed.

Print " x = " + x
Print " b = " + b
Print

; But x is really a little bigger.

Print " x - 14 = " + (x - 14)
Print " b - 14 = " + (b - 14)

WaitKey() : End



impersonalis(Posted 2007) [#8]
2Floyd:
thanks. I`m understand now.
Use DLL on C++ for calculating =|


bytecode77(Posted 2007) [#9]
weird: this doesnt work.
but if i use
If VertexX(...) = VertexY(...)
it works!


H&K(Posted 2007) [#10]
Isnt this why nassa lost one of the Mars rockets?
Thats is rounding error?


bytecode77(Posted 2007) [#11]
no, nasa lost one of the rockets because some fool mixed up inches with cm


impersonalis(Posted 2007) [#12]
#include<iostream.h>
#include<conio.h>

template<class abstr>
void calc(abstr formal)
{	
	cout<<"===\n";
	cout<<"for "<<sizeof(formal)<<" bytes"<<endl;
	abstr intervalx[20];
	abstr temp0,temp1,temp2,b;
	short tempc;
	abstr x=14.143;
	abstr xmax=15.051;
	abstr h=0.242;
	temp0=13.417;
	tempc=1;
	while(temp0<=xmax){
		temp2=temp0+h;
		intervalx[tempc]=temp2;
		temp0=temp2;
		tempc++;
	}

	b=intervalx[3];

	if(x==b)
		cout<<x<<"="<<b<<endl;
	else
		cout<<x<<"!="<<b<<endl;
	cout<<"===\n";
	
}

void main()
{
	float x1;
	double x2;
	calc(x1);
	calc(x2);
	cout<<endl;
	getch();
}

Output:

===
for 4 bytes
14.143!=14.143
===
===
for 8 bytes
14.143=14.143
===


Conclusion: use DLL with 8-byte variable (double)


H&K(Posted 2007) [#13]
no, nasa lost one of the rockets because some fool mixed up inches with cm
Thats a different one. They lost one because of cm/inches they lost another because of imperial screw sizes being different to metric screw sizes and they lost another because of rounding error


Dreamora(Posted 2007) [#14]
With double anything is more or less accurate enough. But double is not CPU accelerated as CPU is always opted for INT and FLOAT, so you sacrifice a fair amount of time for nothing.

As mentioned above, use fixed point accuracy, then you won't have any problems at all. Thats how large scale engines tend to work. (because float comparision gets quite useless quite fast. Its very accurate around 0, but the large the number gets the less accurate it is. Something fixed point does not have.)