float/double zero division

This forum is meant for questions and discussions about the X# language and tools
Karl-Heinz
Posts: 774
Joined: Wed May 17, 2017 8:50 am

float/double zero division

Post by Karl-Heinz »

Hi Chris,

here are some test i made to check a float/double zero division. It seems that ? and AsString() causes the app to hang. There´s also a situation where floats and doubles behave different.

Code: Select all

FUNCTION Start() A VOID
LOCAL x := 3.00 AS FLOAT     //  -3.00
LOCAL y := 0.00 AS FLOAT  
LOCAL divResult AS FLOAT    

/*
LOCAL x := 3.00 AS double     //  -3.00
LOCAL y := 0.00 AS double  
LOCAL divResult AS double   
*/

	? "Start"
	?  
	divResult := x / y 
	? 

// 	? divResult  // the app hangs
//	? AsString ( divResult )  // the app hangs
//	VAR c := AsString ( divResult )  // the app hangs
	
	Console.WriteLine ( divResult )  // ok, +unendlich 
	
//	? AsString ( x / y  )  // the app hangs
	
//	? double.PositiveInfinity  // the app hangs
	? double.PositiveInfinity:ToString() // this works 	
	?
	Console.WriteLine ( double.PositiveInfinity )  // ok, +unendlich  
	
//  the comparison gives - correctly - true if a double is used, 
//  but false with a float.
    
    IF divResult == double.PositiveInfinity 
		? "PositiveInfinity"
		?
	ENDIF 
	
	// ok , true - no matter if floats or doubles are used	 
	// Seems to be the only way to detect infinity if floats are used.
	    
	IF Double.IsInfinity( divResult )
		divResult := 9.99
		
	ENDIF
	
	? divResult  // ok  9.99
		 
	?  
	
RETURN
regards
Karl-Heinz
User avatar
Chris
Posts: 4562
Joined: Thu Oct 08, 2015 7:48 am
Location: Greece

float/double zero division

Post by Chris »

Thanks Karl-Heinz, both problems confirmed, will take care of them!
Chris Pyrgas

XSharp Development Team test
chris(at)xsharp.eu
Karl-Heinz
Posts: 774
Joined: Wed May 17, 2017 8:50 am

float/double zero division

Post by Karl-Heinz »

Guys,

how do you handle a float zero division result ?

Code: Select all

fValue := 34.12 / 0  

? fValue         // +unendlich

? fValue * 3.34  // +unendlich

Of course, something like this causes a System.OverflowException.

Code: Select all

? Round ( fValue , 2 )  
the RDD system seems to take care of such divisions:

Code: Select all

fieldput ( 1 , fValue )  

? fieldget ( 1 )  //  shows correctly 0.00 
a workaround is to use a func like:

Code: Select all

FUNCTION FloatDivision ( f1 AS FLOAT , f2 AS FLOAT ) AS FLOAT
LOCAL fResult AS FLOAT

	fResult := f1 / f2 
	
	IF Double.IsInfinity( fResult )
		fResult := 0.00 
				
	ENDIF 
	
	RETURN fResult

 
what do you think ?
might a compiler enhancement take care of such zero divisions ?

regards
Karl-Heinz
FFF
Posts: 1522
Joined: Fri Sep 25, 2015 4:52 pm
Location: Germany

float/double zero division

Post by FFF »

Karl-Heinz,
maybe i'm too much in holiday mode, but a division by 0 results certainly NOT in Zero. So, i don't want to see the result from your workaround, nor would i want to get silently 0.00 in my table, if the RDD indeed does as you describe.
Regards
Karl
(on Win8.1/64, Xide32 2.19, X#2.19.0.2.)
User avatar
lumberjack
Posts: 723
Joined: Fri Sep 25, 2015 3:11 pm

float/double zero division

Post by lumberjack »

Karl,
FFF wrote:Karl-Heinz,
maybe i'm too much in holiday mode, but a division by 0 results certainly NOT in Zero. So, i don't want to see the result from your workaround, nor would i want to get silently 0.00 in my table, if the RDD indeed does as you describe.
I think this is already catered for in the compiler switches /ovf and /fovf, but I would say it is the wrong way around. Currently if not set, it silently replace with 0 / 0.0; Robert/Chris maybe need to give us a summary, since the Help indicates it is only with the Vulcan/VO dialects used. What is the handling in X# Core for overflows? I assume overflow exception raised?

I would rather prefer the standard to be to throw an exception and use the /ovf and /fovf to treat it as 0 if needed or handled it programatically.

I do have scenarios where due to mathematical algorithms I need a zero since working with very small number arithmetic, and sometimes difficult to emulate/test since it is almost impossible to create a Unit Test case for it. My oldest case was in the late 80's where some code originally developed in Fortran ran happily for 8 years when suddenly it just did not work in a specific scenario. Took us months to find the culprit, which in the end was somebody have entered details quite correctly, problem was his specific scenario calculated exactly an Internal Rate of Return (IRR) = 0 (take note this was still on a mainframe IBM, so no debugger). So yes we added a check, but needless to say that same code still is basically running unmodified today, and we have never experienced somebody with a scenario again resulting in IRR = 0.
Just my 2c.
User avatar
Chris
Posts: 4562
Joined: Thu Oct 08, 2015 7:48 am
Location: Greece

float/double zero division

Post by Chris »

Hmm, looks like this is a bug, at least when overflow checking is enabled, then a division by (float) zero should throw an exception (at least in the VO dialect), same with what VO does. It already throws an exception for dividing by (integer) zero.
Chris Pyrgas

XSharp Development Team test
chris(at)xsharp.eu
Karl-Heinz
Posts: 774
Joined: Wed May 17, 2017 8:50 am

float/double zero division

Post by Karl-Heinz »

Hi Johan,

just to clarify: I´m using the VO-dialect and the used fValue is a float

Local fValue as float

such a float zero division doesn´t throw an exception. The return value is either +infinity or -infinity, and it doesn´t matter if the settings /ovf and /fovf are checked or unchecked. A double behaves the same, but if fValue is a decimal, the fValue assignment throws an System.InvalidCastException exception.

>> Currently if not set, it silently replace with 0 / 0.0

are you sure ?

regards
Karl-Heinz
Karl-Heinz
Posts: 774
Joined: Wed May 17, 2017 8:50 am

float/double zero division

Post by Karl-Heinz »

Guys,

i made a VO core test. The *only* compiler switch that´s checked is /vo8. If decimals are used i see a DivideByZero exception, otherwise +Infinity.

Code: Select all

#define __USE_DECIMAL__ 1

FUNCTION Start( ) AS VOID 
	
#IFDEF __USE_DECIMAL__	

LOCAL fValue AS decimal
LOCAL i AS decimal 

	? "Decimal" 
	?
	i := 0.00m

  fValue := 34.12m / i  
  
#ELSE

LOCAL fValue AS DOUBLE 
LOCAL i AS DOUBLE 

	? "Double"

	i := 0.00

  fValue := 34.12 / i  


#ENDIF   
  

 ? fValue  // +Infinity
  
RETURN 
regards
Karl-Heinz
User avatar
lumberjack
Posts: 723
Joined: Fri Sep 25, 2015 3:11 pm

float/double zero division

Post by lumberjack »

Hi Karl-Heinz,
Karl-Heinz wrote: >> Currently if not set, it silently replace with 0 / 0.0
are you sure ?
No I am not sure, hence why I asked Robert/Chris to maybe shed some light. Unfortunately all my math calculations has to be done with exception testing, hence I cannot rely on a compiler setting, I need an exception when overflow takes place in my scenarios and investigate why it occurs.

As an example to show what I am working with, just 2 macro compiled codeblocks from one of my simulation environments:

Code: Select all

{|oM,nA,a| a:=oM:aPar, ;
          nA:=oM:nAge-oM:nTimeLag - oM:nShock, ;
          (a[1] + a[2]*log(oM:nSPH) + ;
          a[3]*(oM:nSPH/100)^2) * (1-exp(-nA/(a[4] + a[5]*log(oM:nSPH) + ;
          a[6]/oM:nSPH + a[7]*(oM:nSPH/100)^2)))^(a[8] + ;
          a[9]/oM:nSPH + a[10]*log(oM:nSPH) + a[11]*oM:nSPH)}
{|oM,a,nX,nI1,nI2| a:=oM:aPar, ;
          nX:=oM:nHt1/oM:nHgt, ;
          nI1:=iif(nX<=a[5],1,0), ;
          nI2:=iif(nX<=a[6],1,0), ;
          (1/0.408004710919776)*((a[2]/3)*nX^3 + ;
          (a[1]/2)*nX^2-(a[1]+a[2])*nX-(a[3]/3)*((a[5]-nX)^3*nI1-a[5]^3) - ;
          (a[4]/3)*((a[6]-nX)^3*nI2-a[6]^3)) }
All this is handled by one Equation class and a couple of wrapper Driver classes with the business logic in them...
Karl-Heinz
Posts: 774
Joined: Wed May 17, 2017 8:50 am

float/double zero division

Post by Karl-Heinz »

Hi Johan,

i give up :woohoo:

I do not envy anyone who needs to work with this source code at some point ;-)

regards
Karl-Heinz
Post Reply