Passigs Double/Float test passed

Just starting out? Need help? Post your questions and find answers here.
User avatar
langinagel
Enthusiast
Enthusiast
Posts: 131
Joined: Fri Jan 28, 2005 11:53 pm
Location: Germany
Contact:

Passigs Double/Float test passed

Post by langinagel »

In her german book "Weniger schlecht Programmieren" Kathrin Passig says that the following code will fail in almost all programming languages:

Code: Select all

        double a = 0.7;
	double b = 0.9;
	double x = a + 0.1;
	double y = b - 0.1;
	if (x == y) {
		printf(" all fine");
	}
	else {
		printf( " it failed ");
	}
She is right on C (current GCC compiler).

Curiously I tried it with Purebasic:

Code: Select all

OpenConsole()
ad.d = 0.7
bd.d = 0.9
xd = ad + 0.1
yd = bd - 0.1

If xd = yd
  PrintN("Purebasic can do with double")
Else
  Print("PB is all the same on double")
EndIf

af.f = 0.7
bf.f = 0.9
xf = af + 0.1
yf = bf - 0.1

If xf = yf
  PrintN("Purebasic can do with float")
Else
  Print("PB is all the same with float")
EndIf

Input()
and I got a surprising good result (on PB 5.30 Linux-x86).

Is this coincidence? Or is there anything better with PB?
https://www.doerpsoft.org

Boost. Work. Efficiency.
User avatar
Danilo
Addict
Addict
Posts: 3036
Joined: Sat Apr 26, 2003 8:26 am
Location: Planet Earth

Re: Passigs Double/Float test passed

Post by Danilo »

xd and yd should be defined as double. They are Integer now (Default type, .i).
xf and yf should be defined as float. They are Integer now (Default type, .i).

Added code:

Code: Select all

PrintN(""+xd+"="+yd)
PrintN(""+xf+"="+yf)
Output:

Code: Select all

1=1
1=1
:D

After the correction:

Code: Select all

OpenConsole()
ad.d = 0.7
bd.d = 0.9
xd.d = ad + 0.1
yd.d = bd - 0.1

If xd = yd
  PrintN("all fine with double")
Else
  PrintN("it failed with double")
EndIf
PrintN("")
PrintN("xd: "+StrD(xd,20))
PrintN("yd: "+StrD(yd,20))

PrintN("")
PrintN("------------------------------")

af.f = 0.7
bf.f = 0.9
xf.f = af + 0.1
yf.f = bf - 0.1

If xf = yf
  PrintN("all fine with float")
Else
  PrintN("it failed with float")
EndIf
PrintN("")
PrintN("xf: "+StrF(xf,20))
PrintN("yf: "+StrF(yf,20))

Input()
User avatar
langinagel
Enthusiast
Enthusiast
Posts: 131
Joined: Fri Jan 28, 2005 11:53 pm
Location: Germany
Contact:

Re: Passigs Double/Float test passed

Post by langinagel »

:shock:

Thanks Danilo.

:oops:
Lesson learned:
I have to check my code better before posting "surprising" results.
Mea culpa.
https://www.doerpsoft.org

Boost. Work. Efficiency.
User avatar
blueznl
PureBasic Expert
PureBasic Expert
Posts: 6166
Joined: Sat May 17, 2003 11:31 am
Contact:

Re: Passigs Double/Float test passed

Post by blueznl »

I never understood how ol' GFAbasic did this, but IIRC there it would pass this test. I should reinstall it one of these days and see if I remember correctly.
( PB6.00 LTS Win11 x64 Asrock AB350 Pro4 Ryzen 5 3600 32GB GTX1060 6GB)
( The path to enlightenment and the PureBasic Survival Guide right here... )
Thorium
Addict
Addict
Posts: 1305
Joined: Sat Aug 15, 2009 6:59 pm

Re: Passigs Double/Float test passed

Post by Thorium »

blueznl wrote:I never understood how ol' GFAbasic did this, but IIRC there it would pass this test. I should reinstall it one of these days and see if I remember correctly.
It's commonly done by doing rounded comparisions.
Thorium
Addict
Addict
Posts: 1305
Joined: Sat Aug 15, 2009 6:59 pm

Re: Passigs Double/Float test passed

Post by Thorium »

Here is a rounded compare. It rounds to 3 digits and compares.

Code: Select all

OpenConsole()
ad.d = 0.7
bd.d = 0.9
xd.d = ad + 0.1
yd.d = bd - 0.1

If Round(xd*1000, #PB_Round_Nearest)/1000 = Round(yd*1000, #PB_Round_Nearest)/1000
  PrintN("all fine with double")
Else
  PrintN("it failed with double")
EndIf
PrintN("")
PrintN("xd: "+StrD(xd,20))
PrintN("yd: "+StrD(yd,20))
PrintN("xd rounded: "+StrF(Round(xd*1000, #PB_Round_Nearest)/1000,20))
PrintN("xd rounded: "+StrF(Round(yd*1000, #PB_Round_Nearest)/1000,20))

PrintN("")
PrintN("------------------------------")

af.f = 0.7
bf.f = 0.9
xf.f = af + 0.1
yf.f = bf - 0.1

If Round(xf*1000, #PB_Round_Nearest)/1000 = Round(yf*1000, #PB_Round_Nearest)/1000
  PrintN("all fine with float")
Else
  PrintN("it failed with float")
EndIf
PrintN("")
PrintN("xf: "+StrF(xf,20))
PrintN("yf: "+StrF(yf,20))
PrintN("xf rounded: "+StrF(Round(xf*1000, #PB_Round_Nearest)/1000,20))
PrintN("xf rounded: "+StrF(Round(yf*1000, #PB_Round_Nearest)/1000,20))

Input()
User avatar
blueznl
PureBasic Expert
PureBasic Expert
Posts: 6166
Joined: Sat May 17, 2003 11:31 am
Contact:

Re: Passigs Double/Float test passed

Post by blueznl »

Thorium wrote:
blueznl wrote:I never understood how ol' GFAbasic did this, but IIRC there it would pass this test. I should reinstall it one of these days and see if I remember correctly.
It's commonly done by doing rounded comparisions.
Hmmm. I'm not totally convinced :-) I always suspected them of doing some 'behind the scenes' manipulation using shifted decimals. I know I've used that approach myself sometimes in some financial application where I had to deal with very large and very small numbers. I was using three elements, float flag, base, exponent, like this:

2.5 = 2.5 x 10^0 and would be stored as 0 25 0
25 = 2.5 x 10^1 and would be stored as 0 25 1
250000000 = 2.5 x 10^8 and would be stored as 0 25 8
2/3 wouldn't fit in that scheme and would be stored as a 1 followed by a float

I must have some of that code somewhere, figuring out when to pick what format was a bit tricky. IIRC the root trigger was that the floats weren't accurate enough for certain things. Even worse, the biggest Int was 64k so I wrote my own little math lib in 6502 assembly to handle larger numbers. (It was some software that calculated the pricing of electronic components in large numbers, ie. very low component prices, and pretty big total numbers. Ah... long ago, when I was still young...)
( PB6.00 LTS Win11 x64 Asrock AB350 Pro4 Ryzen 5 3600 32GB GTX1060 6GB)
( The path to enlightenment and the PureBasic Survival Guide right here... )
Thorium
Addict
Addict
Posts: 1305
Joined: Sat Aug 15, 2009 6:59 pm

Re: Passigs Double/Float test passed

Post by Thorium »

VB6 did it like that.
And Siemens Sinumerik high language extension for CNC does it also this way. On Sinumerik you can actually specify the compare precision.
Post Reply