fbpx
Welcome, Guest
Username: Password: Remember me
  • Page:
  • 1

TOPIC: .net is a extremly dangerous thing ;-)

.net is a extremly dangerous thing ;-) 9 months 3 weeks ago #5940

  Karl-Heinz's Avatar Topic Author Karl-Heinz Offline Posts: 269
FUNCTION DoConsole2() AS VOID
LOCAL fTotal AS double
VAR aDouble := <OBJECT>{0.00,276.45,276.45}

Console.WriteLine("{0,12:###,##0.00}" + "{1,12:###,##0.00}" + "{2,20:###,###,##0.00}" , aDouble) 
fTotal += (double) aDouble [ 3 ] 

aDouble [ 1 ] := -1223.56  
aDouble [ 2 ] := 7869
aDouble [ 3 ] := (double) aDouble [ 1 ] + (double) aDouble [ 2 ]

Console.WriteLine("{0,12:###,##0.00}" + "{1,12:###,##0.00}" + "{2,20:###,###,##0.00}" , aDouble) 
fTotal += (double) aDouble [ 3 ] 


// 12 + 12 == 24
Console.WriteLine(space ( 24 ) + repl ( "-" , 20 ) )
// 12 + 12 + 20 == 44
Console.WriteLine("{0,44:###,###,##0.00}" , fTotal )
                                                    
RETURN


find the (runtime) problem ;-)

regards
Karl-Heinz

Please Log in or Create an account to join the conversation.

.net is a extremly dangerous thing ;-) 9 months 3 weeks ago #5941

  wriedmann's Avatar wriedmann Away Posts: 1573
Hi Karl-Heinz,

I had similar problems with conversions....

It is very bad that .NET does not handles this and that you have to specify
aDouble [ 1 ] := -1223.56d  
aDouble [ 2 ] := 7869d

Wolfgang
Wolfgang Riedmann
Meran, South Tyrol, Italy
This email address is being protected from spambots. You need JavaScript enabled to view it.
www.riedmann.it - docs.xsharp.it

Please Log in or Create an account to join the conversation.

Last edit: by wriedmann. Reason: Correction of code

.net is a extremly dangerous thing ;-) 9 months 3 weeks ago #5942

  wriedmann's Avatar wriedmann Away Posts: 1573
Hi Karl-Heinz,

an addition: this works also:
aDouble [ 1 ] := ( double ) -1223.56
aDouble [ 2 ] := ( double ) 7869

In our VO understanding a numeric is a numeric and there is no runtime error when they are converted for and back.
It is really a pity that a numeric calculation between an int32 and a double fails at runtime!

Wolfgang
Wolfgang Riedmann
Meran, South Tyrol, Italy
This email address is being protected from spambots. You need JavaScript enabled to view it.
www.riedmann.it - docs.xsharp.it

Please Log in or Create an account to join the conversation.

.net is a extremly dangerous thing ;-) 9 months 3 weeks ago #5943

  Chris's Avatar Chris Away Posts: 1181
Guys,

.Net actually does handle it well, but we must be careful with what we are doing. The code (simplified to make it easier to follow):
aDouble [ 3 ] := (double) aDouble [ 2 ]

Does a type cast from object to double, so we tell the compiler that we know that aDouble [ 2 ] holds a double, which apparently in this case is not true. What we really should be doing, is to use a conversion, not a cast, as in:
aDouble [ 3 ] := Convert.ToDouble( aDouble [ 2 ] )

This will always work correctly, provided that the type of aDouble [ 2 ] can be converted to a double.

Of course he "Convert" method is slower, but it is safer to use in such code.

Chris
XSharp Development Team
chris(at)xsharp.eu

Please Log in or Create an account to join the conversation.

.net is a extremly dangerous thing ;-) 9 months 3 weeks ago #5944

  Chris's Avatar Chris Away Posts: 1181
Hi Wolfgang,

wriedmann wrote: Hi Karl-Heinz,

an addition: this works also:

aDouble [ 1 ] := ( double ) -1223.56
aDouble [ 2 ] := ( double ) 7869

In our VO understanding a numeric is a numeric and there is no runtime error when they are converted for and back.
It is really a pity that a numeric calculation between an int32 and a double fails at runtime!

Wolfgang


To be precise, it is not the calculation that fails, but the cast, which is indeed incorrect. You can do calculations between Int32 and Double just fine:
LOCAL r AS REAL8
LOCAL n AS INT
r := n + r

as long as the target var type is "larger" (or same) than the operands.

But when you are doing calculations between objects that the runtime knows nothing about at compile time (calculation between System.Object types), then you need to convert them to the data type you want first.

Chris
XSharp Development Team
chris(at)xsharp.eu

Please Log in or Create an account to join the conversation.

.net is a extremly dangerous thing ;-) 9 months 3 weeks ago #5945

  Jamal's Avatar Jamal Offline Posts: 123
Not sure this is a .NET thing, but more of a language specific.

I used C# and VB.NET.
C# is very strict on casting, however, VB.NET handles double correctly.

Jamal

Please Log in or Create an account to join the conversation.

Last edit: by Jamal.

.net is a extremly dangerous thing ;-) 9 months 3 weeks ago #5946

  wriedmann's Avatar wriedmann Away Posts: 1573
Hi Chris,

thank you very much for your explanations!

Theoretically also the cast from an int32 to a double should work....

Wolfgang
Wolfgang Riedmann
Meran, South Tyrol, Italy
This email address is being protected from spambots. You need JavaScript enabled to view it.
www.riedmann.it - docs.xsharp.it

Please Log in or Create an account to join the conversation.

.net is a extremly dangerous thing ;-) 9 months 3 weeks ago #5949

  Chris's Avatar Chris Away Posts: 1181
Hi Wolfgang,

wriedmann wrote: Hi Chris,

thank you very much for your explanations!

Theoretically also the cast from an int32 to a double should work....

Wolfgang


They are different data types, with different internal representation, and just because they are both numeric types, does not mean they can be cast one to another (of course conversion is a different thing). It's like expecting to be allowed to do (System.Collections.SortedList)oMyDisctionary, because both SortedList and Dictionary are both collection types.

Try doing the equivalent of casting in VO:
LOCAL n AS INT
LOCAL r AS REAL8
r := 1.2
n := INT(_CAST,r)
? n

this will not throw an exception/error in VO, but the result will not make sense either.

Note that in this particular case, in .Net such a (memory mapped) cast is not allowed, so if you compile this with X# (or vulcan), the compiler will actually create code that makes a conversion! It does that, because it knows at compile time exactly the data types involved (INT and REAL8) and can safely convert from one to another, while it cannot do that for vars declared as Object.

Edit: So, to summarize, my suggestion is when every time when dealing with objects that are non known at compile time, always use the Convert methods to be safe. Unless you want to use USAULs of course, which take care of this at runtime!

Chris
XSharp Development Team
chris(at)xsharp.eu

Please Log in or Create an account to join the conversation.

Last edit: by Chris.

.net is a extremly dangerous thing ;-) 9 months 3 weeks ago #5950

  Karl-Heinz's Avatar Topic Author Karl-Heinz Offline Posts: 269
Guys,

c# throws the same runtime error. The "problem" is that an array of "simple" Objects must be used to feed the Console.WriteLine(), instead of the possibility to use an typed array of e.g. doubles. The lesson learned in conjunction with "simple" Objects: Don´t trust your human senses, especially if you have VO roots ;-)

// something like this gives no such problems.

VAR fDouble := <DOUBLE>{2.50, 3 , 12.45 }

fDouble [ 1 ] := 1234
fDouble [ 2 ] := -12
fDouble [ 3 ] := fDOuble [ 1 ] + fDouble [ 2 ]

? fDouble [ 1 ]
? fDOuble [ 2 ]
? fDouble [ 3 ]

regards
Karl-Heinz

Please Log in or Create an account to join the conversation.

.net is a extremly dangerous thing ;-) 9 months 3 weeks ago #5951

  Karl-Heinz's Avatar Topic Author Karl-Heinz Offline Posts: 269
Hi Chris,

Chris wrote:
Edit: So, to summarize, my suggestion is when every time when dealing with objects that are non known at compile time, always use the Convert methods to be safe. Unless you want to use USAULs of course, which take care of this at runtime!

Chris


So this isn´t save enough ?

aDouble [ 1 ] := (double) -1223.56
aDouble [ 2 ] := (double) 7869
aDouble [ 3 ] := (double) aDouble [ 1 ] + (double) aDouble [ 2 ]

regards
Karl-Heinz

Please Log in or Create an account to join the conversation.

.net is a extremly dangerous thing ;-) 9 months 3 weeks ago #5952

  Chris's Avatar Chris Away Posts: 1181
Hi Karl-Heinz,

Karl-Heinz wrote: So this isn´t save enough ?

aDouble [ 1 ] := (double) -1223.56  
aDouble [ 2 ] := (double) 7869
aDouble [ 3 ] := (double) aDouble [ 1 ] + (double) aDouble [ 2 ]


If aDouble is a an array of Double (and not array of Object), then it is absolutely safe, everything is known at compile time. But this wouldn't be safe, as the type of the oNumeric var is not known at compile time:
LOCAL oNumeric AS OBJECT
o := 1234
aDouble [ 1 ] := (double) oNumeric

In this case, the compiler cannot make any conversion, as it does not know from what type to convert to a Double. So it assumes oNumeric really holds a double, which fails at runtime because it actually holds an INT.

Btw, a note to everybody, this is not a compatibility problem with VO at all, because in VO you could not put numeric values into an OBJECT var...

Chris
XSharp Development Team
chris(at)xsharp.eu

Please Log in or Create an account to join the conversation.

.net is a extremly dangerous thing ;-) 9 months 3 weeks ago #5955

  Karl-Heinz's Avatar Topic Author Karl-Heinz Offline Posts: 269
Hi Chris,

LOCAL oNumeric AS OBJECT
o := 1234
aDouble [ 1 ] := (double) oNumeric

In this case, the compiler cannot make any conversion, as it does not know from what type to convert to a Double. So it assumes oNumeric really holds a double, which fails at runtime because it actually holds an INT.


ok, i got it. i enhanced my sample with a second array:

VAR aDouble2 := <OBJECT>{ -23 , 276.45}

the first Element holds an int, while the second element holds a float, Without to convert aDouble2[1] to a float the program crashes.

FUNCTION DoConsole2() AS VOID
LOCAL fTotal AS double
VAR aDouble := <OBJECT>{0.00,276.45,276.45}
VAR aDouble2 := <OBJECT>{-23,276.45}


Console.WriteLine("{0,12:###,##0.00}" + "{1,12:###,##0.00}" + "{2,20:###,###,##0.00}" , aDouble) 
fTotal += (double) aDouble [ 3 ]

aDouble [ 1 ] := (double)  -1223.56  
aDouble [ 2 ] := (double) 122
aDouble [ 3 ] := (double) aDouble [ 1 ] + (double) aDouble [ 2 ]

Console.WriteLine("{0,12:###,##0.00}" + "{1,12:###,##0.00}" + "{2,20:###,###,##0.00}" , aDouble) 
fTotal += (double) aDouble [ 3 ] 

// aDouble [ 1 ] :=  (double) aDouble2 [ 1 ]  // this fails at runtime because aDouble2[1] holds an none float -> -23  
// aDouble [ 2 ] :=  (double) aDouble2 [ 2 ]  // this would work, because aDouble2[2] already holds a float -> 276.45

aDouble [ 1 ] := Convert.ToDouble  ( aDouble2 [ 1 ]  )  
aDouble [ 2 ] := Convert.ToDouble  ( aDouble2 [ 2 ]  )
aDouble [ 3 ] := (double) aDouble [ 1 ] + (double) aDouble [ 2 ]

Console.WriteLine("{0,12:###,##0.00}" + "{1,12:###,##0.00}" + "{2,20:###,###,##0.00}" , aDouble) 
fTotal += (double) aDouble [ 3 ] 

// 12 + 12 == 24
Console.WriteLine(space ( 24 ) + repl ( "-" , 20 ) )
// 12 + 12 + 20 == 44          

Console.WriteLine("{0,44:###,###,##0.00}" , fTotal )
                                                     

RETURN

regards
Karl-Heinz

Please Log in or Create an account to join the conversation.

.net is a extremly dangerous thing ;-) 9 months 3 weeks ago #5957

  FFF's Avatar FFF Away Posts: 577
Karl-Heinz,
with this:
VAR aDouble2 := <OBJECT>{ -23 , 276.45}
i think, you FORCE the compiler to treat the numbers as OBJECT, i.e. you "forbid" it to be "clever" and deduct the type.

Karl

Please Log in or Create an account to join the conversation.

Last edit: by FFF. Reason: typo

.net is a extremly dangerous thing ;-) 9 months 3 weeks ago #5961

  wriedmann's Avatar wriedmann Away Posts: 1573
Hi Karl-Heinz,

IMHO the misunderstanding is here:
in VO we use
float( _cast, uValue )
to cast, and
float( uValue )
to convert.

In .NET,
(double) oObject
is a cast, and not a conversion, and since we don't work on pointers anymore, the code crashes.

Wolfgang
Wolfgang Riedmann
Meran, South Tyrol, Italy
This email address is being protected from spambots. You need JavaScript enabled to view it.
www.riedmann.it - docs.xsharp.it

Please Log in or Create an account to join the conversation.

.net is a extremly dangerous thing ;-) 9 months 3 weeks ago #5965

  Karl-Heinz's Avatar Topic Author Karl-Heinz Offline Posts: 269
Hi Karl,

FFF wrote: Karl-Heinz,
with this:
VAR aDouble2 := <OBJECT>{ -23 , 276.45}
i think, you FORCE the compiler to treat the numbers as OBJECT, i.e. you "forbid" it to be "clever" and deduct the type.


Yes, that´s what i wanted ;-)

[...]

VAR aDouble2 := <OBJECT>{ -23 , 276.45}

the first Element holds an int, while the second element holds a float, Without to convert aDouble2[1] to a float the program crashes.

[...]

To round things off, i added another array, a <double> array,

FUNCTION DoConsole2() AS VOID
LOCAL fTotal AS double
VAR aDouble := <OBJECT>{0.00,276.45,276.45}
VAR aDouble2 := <OBJECT>{-23,276.45}
VAR aDouble3 := <DOUBLE>{123 ,-1276.45}

Console.WriteLine("{0,12:###,##0.00}" + "{1,12:###,##0.00}" + "{2,20:###,###,##0.00}" , aDouble) 
fTotal += (double) aDouble [ 3 ]

aDouble [ 1 ] := (double)  -1223.56  
aDouble [ 2 ] := (double) 122
aDouble [ 3 ] := (double) aDouble [ 1 ] + (double) aDouble [ 2 ]

Console.WriteLine("{0,12:###,##0.00}" + "{1,12:###,##0.00}" + "{2,20:###,###,##0.00}" , aDouble) 
fTotal += (double) aDouble [ 3 ] 

// aDouble [ 1 ] :=  (double) aDouble2 [ 1 ]  // this fails because aDouble2[1] holds an none float -> -23  
// aDouble [ 2 ] :=  (double) aDouble2 [ 2 ]  // this would work, because aDouble2[1] holds already a float -> 276.45

aDouble [ 1 ] := Convert.ToDouble  ( aDouble2 [ 1 ]  )  
aDouble [ 2 ] := Convert.ToDouble  ( aDouble2 [ 2 ]  )
aDouble [ 3 ] := (double) aDouble [ 1 ] + (double) aDouble [ 2 ]

Console.WriteLine("{0,12:###,##0.00}" + "{1,12:###,##0.00}" + "{2,20:###,###,##0.00}" , aDouble) 
fTotal += (double) aDouble [ 3 ]

aDouble [ 1 ] := aDouble3 [ 1 ]  // <DOUBLE> array - no cast or convert necessary  > 123
aDouble [ 2 ] := aDouble3 [ 2 ]  // <DOUBLE> array - no cast or convert necessary  > -1276.45
aDouble [ 3 ] := (double) aDouble [ 1 ] + (double) aDouble [ 2 ]

Console.WriteLine("{0,12:###,##0.00}" + "{1,12:###,##0.00}" + "{2,20:###,###,##0.00}" , aDouble) 
fTotal += (double) aDouble [ 3 ]  

// 12 + 12 == 24
Console.WriteLine(space ( 24 ) + repl ( "-" , 20 ) )
// 12 + 12 + 20 == 44          
Console.WriteLine("{0,44:###,###,##0.00}" , fTotal )
                                                     

RETURN

regards
Karl-Heinz

Please Log in or Create an account to join the conversation.

  • Page:
  • 1