If someone can explain it to me?
- softdevo@tiscali.it
- Posts: 191
- Joined: Wed Sep 30, 2015 1:30 pm
If someone can explain it to me?
For those who have not read the image correctly, here is the simplification of the code under discussion:
(As I said, the same code in another application gives the right result: 870)
LOCAL cOre AS STRING
LOCAL nNUORE AS System.Double
LOCAL nTOMIC AS System.Double
cOre := SELF:Gior:Text // "8,70"
nNUORE := Val(cOre) // 8.70
nTOMIC := (System.Double)(nNUORE*100,0) // 869.99999999999989 ERROR!!!!!!!!!!!!!!
Danilo
(As I said, the same code in another application gives the right result: 870)
LOCAL cOre AS STRING
LOCAL nNUORE AS System.Double
LOCAL nTOMIC AS System.Double
cOre := SELF:Gior:Text // "8,70"
nNUORE := Val(cOre) // 8.70
nTOMIC := (System.Double)(nNUORE*100,0) // 869.99999999999989 ERROR!!!!!!!!!!!!!!
Danilo
- softdevo@tiscali.it
- Posts: 191
- Joined: Wed Sep 30, 2015 1:30 pm
If someone can explain it to me?
excuse me
LOCAL cOre AS STRING
LOCAL nNUORE AS System.Double
LOCAL nTOMIC AS System.Double
cOre := SELF:Gior:Text // "8,70"
nNUORE := Val(cOre) // 8.70
nTOMIC := (System.Double)(nNUORE*100) // 869.99999999999989
LOCAL cOre AS STRING
LOCAL nNUORE AS System.Double
LOCAL nTOMIC AS System.Double
cOre := SELF:Gior:Text // "8,70"
nNUORE := Val(cOre) // 8.70
nTOMIC := (System.Double)(nNUORE*100) // 869.99999999999989
If someone can explain it to me?
Ciao Danilo,
if you put that value to a database field with 2 decimals, or display it using a picture, it is rounded to a correct value.
I have these issues in VO all the time, and therefore I'm using Round() a lot, other than setting SetFloatDelta() to 0.0001.
In .NET fortunately we have the "decimals" datatype, and AFAIK it is the datatype the X# runtime uses internally for decimal numbers.
Wolfgang
if you put that value to a database field with 2 decimals, or display it using a picture, it is rounded to a correct value.
I have these issues in VO all the time, and therefore I'm using Round() a lot, other than setting SetFloatDelta() to 0.0001.
In .NET fortunately we have the "decimals" datatype, and AFAIK it is the datatype the X# runtime uses internally for decimal numbers.
Wolfgang
Wolfgang Riedmann
Meran, South Tyrol, Italy
wolfgang@riedmann.it
https://www.riedmann.it - https://docs.xsharp.it
Meran, South Tyrol, Italy
wolfgang@riedmann.it
https://www.riedmann.it - https://docs.xsharp.it
- softdevo@tiscali.it
- Posts: 191
- Joined: Wed Sep 30, 2015 1:30 pm
If someone can explain it to me?
Thanks Wolfgang, since the number is always a whole I solved this
nTOMIC := (System.Double)Round(nNUORE*100,0) //(System.Double)(nNUORE*100) //
But the problem remains …
Danilo
nTOMIC := (System.Double)Round(nNUORE*100,0) //(System.Double)(nNUORE*100) //
But the problem remains …
Danilo
If someone can explain it to me?
Hi Danilo,
the problem is not a problem of VO or X#, but a problem in the Microsoft Floating Point Library, or better in the representation of float or double. The float or real8 datatype was never planned for exact calculations, unfortunately.
Use System.Decimal whenever possible.
Wolfgang
the problem is not a problem of VO or X#, but a problem in the Microsoft Floating Point Library, or better in the representation of float or double. The float or real8 datatype was never planned for exact calculations, unfortunately.
Use System.Decimal whenever possible.
Wolfgang
Wolfgang Riedmann
Meran, South Tyrol, Italy
wolfgang@riedmann.it
https://www.riedmann.it - https://docs.xsharp.it
Meran, South Tyrol, Italy
wolfgang@riedmann.it
https://www.riedmann.it - https://docs.xsharp.it
If someone can explain it to me?
Danilo, please try this code in VO, or any other language:
Similarly in c#:
In both samples, you would expect f1 == f2 == 0.45, but both samples return FALSE for == and TRUE for <. This is because none of those values can be represented in binary accurately, there is some precision loss, and the more arithmetic you do with decimal numbers, the more precision is lost.
When you store 0.015 in the f1 var, the actual value stored is something like 0.0149999999791 or similar, because there is no way to represent 0.015 in binary notation that the REAL8, REAL4, FLOAT etc types use. Yes, when you see the value in the debugger or print it with a function, you will usually see 0.015, but this is because there is a runtime function used to print the value, and this is smart, knowing about the precision lost and converts 0.0149999999791 to 0.015 before displaying it. But after a number of calculations with float numbers, you end up with accumulated precision lost in each calculation, so the end result is slightly wrong, and this is why you see this strange value in the debugger sometimes and sometimes not.
For this reason, there is the Decimal type in .Net, which does not store values in binary format internally, but uses a decimal representation. This makes it much slower, but also has zero precision lost, 0.015 will always be 0.015 with this type.
Code: Select all
FUNCTION Start() AS INT
LOCAL f1 AS REAL8
LOCAL f2 AS REAL8
SetFloatDelta(0)
f1 := 0.015
f1 := f1 + f1 + f1
f1 *= 10.0
f2 := 0.45
? f1==f2 , f1<f2 , f1>f2
WAIT
RETURN 0
Code: Select all
public class Program
{
static void Main()
{
double f1;
double f2;
f1 = 0.015;
f1 = f1 + f1 + f1;
f1 *= 10.0;
f2 = 0.45;
System.Console.WriteLine(f1==f2);
System.Console.WriteLine(f1<f2);
System.Console.WriteLine(f1>f2);
}
}
When you store 0.015 in the f1 var, the actual value stored is something like 0.0149999999791 or similar, because there is no way to represent 0.015 in binary notation that the REAL8, REAL4, FLOAT etc types use. Yes, when you see the value in the debugger or print it with a function, you will usually see 0.015, but this is because there is a runtime function used to print the value, and this is smart, knowing about the precision lost and converts 0.0149999999791 to 0.015 before displaying it. But after a number of calculations with float numbers, you end up with accumulated precision lost in each calculation, so the end result is slightly wrong, and this is why you see this strange value in the debugger sometimes and sometimes not.
For this reason, there is the Decimal type in .Net, which does not store values in binary format internally, but uses a decimal representation. This makes it much slower, but also has zero precision lost, 0.015 will always be 0.015 with this type.
Chris Pyrgas
XSharp Development Team
chris(at)xsharp.eu
XSharp Development Team
chris(at)xsharp.eu
If someone can explain it to me?
Hi Wolfgang,
REAL8 and FLOAT use 8 bytes for representing the stored value, in binary format. REAL8 is a synonym for the .Net type System.Double, FLOAT is a special class which again uses a System.Double and also includes formatting info as in VO.
REAL4 uses 4 bytes, in binary format again, it is a synonym for System.Single.
When you want to use the Decimal type, you need to specify it explicitly.
X# is working exactly as in VO:wriedmann wrote: In .NET fortunately we have the "decimals" datatype, and AFAIK it is the datatype the X# runtime uses internally for decimal numbers.
REAL8 and FLOAT use 8 bytes for representing the stored value, in binary format. REAL8 is a synonym for the .Net type System.Double, FLOAT is a special class which again uses a System.Double and also includes formatting info as in VO.
REAL4 uses 4 bytes, in binary format again, it is a synonym for System.Single.
When you want to use the Decimal type, you need to specify it explicitly.
Chris Pyrgas
XSharp Development Team
chris(at)xsharp.eu
XSharp Development Team
chris(at)xsharp.eu
- softdevo@tiscali.it
- Posts: 191
- Joined: Wed Sep 30, 2015 1:30 pm
If someone can explain it to me?
Ok guys, thanks to everyone, everything is clear.
Now I ask if I use System.Decimal instead of System.Double in my calculation class for attendance management that makes thousands of operations on decimal numbers, will the slowness of the decimal be appreciable or irrelevant?
Danilo
Now I ask if I use System.Decimal instead of System.Double in my calculation class for attendance management that makes thousands of operations on decimal numbers, will the slowness of the decimal be appreciable or irrelevant?
Danilo
- lumberjack
- Posts: 727
- Joined: Fri Sep 25, 2015 3:11 pm
- Location: South Africa
If someone can explain it to me?
Danilo,
Think we get the idea, we heavily making use of floating point calculations and we end up with (2.0 / 3.0) that cannot be represented exactly, we cannot get past that, but we can minimize the impact:
So yes it will have an impact, but you can minimize that impact that reduce the number of floating point arithmetic calculations. This is an extreme example but the impact will be reduced aka. speed up the process.
In a single non-looped actual implementation it should not distract the user experience. Try where possible to eliminate floating point bottlenecks.
Hope that helps,
It all depends, will try to explain with a bad coding example:softdevo@tiscali.it wrote:Ok guys, thanks to everyone, everything is clear.
Now I ask if I use System.Decimal instead of System.Double in my calculation class for attendance management that makes thousands of operations on decimal numbers, will the slowness of the decimal be appreciable or irrelevant?
Code: Select all
LOCAL x, y as <SomeFloatType>
x := 1.2 * (2.0 / 3.0) <rest of calculation>
WHILE ctr < 1000000 .AND. x <> 0.0
IF (1.2 * (2.0 / 3.0) <rest of calculation>) < 345.34555
y += 1.2 * (2.0 / 3.0) <rest of calc>
x := 1.2 * (2.0 / 3.0) <rest of change x positively>
ELSE
y -= 1.2 / (2.0 / 3.0) <whatever>
x := 1.2 / (2.0 / 3.0) <rest of change x negatively>
ENDIF
ctr++
ENDDO
Code: Select all
LOCAL x, y as <SomeFloatType>
LOCAL xneg, xpos AS <FloatType>
xneg := 1.2 / (2.0 / 3.0)
xpos := 1.2 * (2.0 / 3.0)
x := xpos <rest of calculation>
WHILE ctr < 1000000 .AND. x <> 0.0
IF (x <rest of calculation>) < 345.34555
y += xpos <rest of calc>
x := xpos <rest of change x positively>
ELSE
y -= xneg <whatever>
x := xneg <rest of change x negatively>
ENDIF
ctr++
ENDDO
In a single non-looped actual implementation it should not distract the user experience. Try where possible to eliminate floating point bottlenecks.
Hope that helps,
______________________
Johan Nel
Boshof, South Africa
Johan Nel
Boshof, South Africa
If someone can explain it to me?
Most probably the speed difference will be irrelevant, because usually in our apps it's other things that slow down performance (disk access, GUI updates etc) and not numeric calculations. Of course I would not use the Decimal type if I wanted to calculate fractals, but for regular calculations, let's say 1,000 or 10,000 numeric calculations per command the difference will be zero. But of course it's always better if you give it a try and see in practice what difference it makes, if any.softdevo@tiscali.it wrote:Ok guys, thanks to everyone, everything is clear.
Now I ask if I use System.Decimal instead of System.Double in my calculation class for attendance management that makes thousands of operations on decimal numbers, will the slowness of the decimal be appreciable or irrelevant?
Danilo
Chris Pyrgas
XSharp Development Team
chris(at)xsharp.eu
XSharp Development Team
chris(at)xsharp.eu