fbpx
Welcome, Guest
Username: Password: Remember me
Welcome to the XSharp forum!

Tell us and our members who you are, what you like and why you became a member of this site.
We welcome all new members and hope to see you around a lot!
  • Page:
  • 1
  • 2

TOPIC: If someone can explain it to me?

If someone can explain it to me? 4 weeks 2 days ago #1

  softdevo@tiscali.it's Avatar Topic Author softdevo@tiscali.it Offline Posts: 80
Look at the attached image: the same code in another application works perfectly, but here .... I just don't understand.
Danilo
Attachments:

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

If someone can explain it to me? 4 weeks 2 days ago #2

  SHirsch's Avatar SHirsch Offline Posts: 91
Hi Danilo,

try using System.Decimal instead of System.Double.

see: www.xsharp.info/forum/public-vo-vn/744-f...eal8-or-decimal#7418

Regards,
Stefan

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

If someone can explain it to me? 4 weeks 2 days ago #3

  FFF's Avatar FFF Offline Posts: 532
Sorry, Danilo,
pls post bigger shots, this one is impossible to read.

Karl

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

If someone can explain it to me? 4 weeks 2 days ago #4

  wriedmann's Avatar wriedmann Offline Posts: 1491
Hi Danilo,
this is how real8 and floats work, and it is that way also in VO.
Look at your SetFloatDelta() setting in both applications.
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.

If someone can explain it to me? 4 weeks 2 days ago #5

  Terry's Avatar Terry Offline Posts: 122
Danilo
The reason for this boils down to rounding errors.

Computations in a digital computer are exact using a number base of 2.
Our understanding is based on a base of 10.

Any conversion will be slightly inaccurate.

To ensure total and absolute consistency in this process every calculation made must be rounded in the same way (up or down). Any compiler will do this in a consistent way.

The downside of this is that the rounding process takes time, and if we require total accuracy, must be done as part of each calculation. When there are thousands of such conversions/calculations to be done this mounts up.

As long as we are dealing with very small rounding errors we need not worry because they will never build up to such an extent as to have any noticeable effect on what we are trying to calculate.

For example, calculating an on-screen pixel position to 2 places of decimals would achieve little.

Floats are designed to calculate numerical results over a huge range, whilst not requiring the additional time-consuming overhead of base numbering scheme conversion.

Therefore, you should never use Floats in any situation where absolute comparisons/values may be required.
They do save time of course, when compared to decimal. It’s a case of “horses for courses”.

Terry
PS Having just read Wolfgang's reply I'm just guessing that SetFloatDelta() gives an accuracy limitation on Floats, allowing the compiler to do things to whatever accuracy is required.
So rather than saying never use Floats, I guess it should be "do not use floats unless SetFloatData() is set.
That is just a guess.

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

Last edit: by Terry. Reason: Just Read Wolfgangs Reply

If someone can explain it to me? 4 weeks 2 days ago #6

  softdevo@tiscali.it's Avatar Topic Author softdevo@tiscali.it Offline Posts: 80
Thanks to all, but I don't understand why with any other value it gives a correct result and only 8.70 gives error, then multiplying by 100 should not generate any rounding.
Another thing I don't understand is why the same code in any other application works.
I will try your suggestions, but I'm not satisfied, because every calculation is therefore in danger.
Danilo

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

If someone can explain it to me? 4 weeks 2 days ago #7

  Chris's Avatar Chris Offline Posts: 1056
Hi Danilo,

Some decimal numbers can be represented better than others. For example, the decimal value 0.625 can be perfectly represented in binary accurately as 0.101, while 0.626 can only be represented in approximation.

The important question is, do you get a problem in your app while running it, or is it just the value you see in the debugger that you do not like? Because normally, when you actually print values to show to the user, you use some kind of rounding, which will eliminate that precision lost.
XSharp Development Team
chris(at)xsharp.eu

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

If someone can explain it to me? 4 weeks 2 days ago #8

  Terry's Avatar Terry Offline Posts: 122
Hi Danilo

Unfortunately, as Karl said, I could not read your post properly.

I made an assumption that it was probably due to rounding errors. I should not have done this - there may be other factors at play here.

We need to see the full code properly.

Sorry if I've managed to steer this discussion in the wrong direction.

Terry

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

If someone can explain it to me? 4 weeks 2 days ago #9

  Chris's Avatar Chris Offline Posts: 1056
No worries Terry, I think both your and Karl's points were valid as well.
XSharp Development Team
chris(at)xsharp.eu

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

If someone can explain it to me? 4 weeks 1 day ago #10

  Terry's Avatar Terry Offline Posts: 122
Thanks Chris. It will be interesting to see what the problem turns out to be.

Terry

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

If someone can explain it to me? 4 weeks 1 day ago #11

  softdevo@tiscali.it's Avatar Topic Author softdevo@tiscali.it Offline Posts: 80
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

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

If someone can explain it to me? 4 weeks 1 day ago #12

  softdevo@tiscali.it's Avatar Topic Author softdevo@tiscali.it Offline Posts: 80
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

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

If someone can explain it to me? 4 weeks 1 day ago #13

  wriedmann's Avatar wriedmann Offline Posts: 1491
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
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.

If someone can explain it to me? 4 weeks 1 day ago #14

  softdevo@tiscali.it's Avatar Topic Author softdevo@tiscali.it Offline Posts: 80
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

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

If someone can explain it to me? 4 weeks 1 day ago #15

  wriedmann's Avatar wriedmann Offline Posts: 1491
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
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.

If someone can explain it to me? 4 weeks 1 day ago #16

  Chris's Avatar Chris Offline Posts: 1056
Danilo, please try this code in VO, or any other language:
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 

Similarly in c#:
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);
	}
}

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.
XSharp Development Team
chris(at)xsharp.eu

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

If someone can explain it to me? 4 weeks 1 day ago #17

  Chris's Avatar Chris Offline Posts: 1056
Hi Wolfgang,

wriedmann wrote: In .NET fortunately we have the "decimals" datatype, and AFAIK it is the datatype the X# runtime uses internally for decimal numbers.


X# is working exactly as in VO:

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.
XSharp Development Team
chris(at)xsharp.eu

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

If someone can explain it to me? 4 weeks 17 hours ago #18

  softdevo@tiscali.it's Avatar Topic Author softdevo@tiscali.it Offline Posts: 80
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

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

If someone can explain it to me? 4 weeks 16 hours ago #19

  lumberjack's Avatar lumberjack Offline Posts: 367
Danilo,

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?

It all depends, will try to explain with a bad coding example:
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
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:
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
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,
______________________
Johan Nel
George, South Africa

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

If someone can explain it to me? 4 weeks 14 hours ago #20

  Chris's Avatar Chris Offline Posts: 1056

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


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.
XSharp Development Team
chris(at)xsharp.eu

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

  • Page:
  • 1
  • 2