Jump to content

mathematical problem with Int()


Recommended Posts

hi there,

got a problem with a mathematical calculation:

$x=8.001
MsgBox(0,$x,int($x))
$var=$x-int($x)
MsgBox(0,$var,String($var))

what is wrong? instead of "0.001" autoit calculates "0.000999999999999946"

my fault or a bug ?

j.

Edited by jennico
Spoiler

I actively support Wikileaks | Freedom for Julian Assange ! | Defend freedom of speech ! | Fight censorship ! | I will not silence.OixB7.jpgDon't forget this IP: 213.251.145.96

 

Link to comment
Share on other sites

Not sure but I think it has to do with how variables are handled. Someone who knows C++ should be able to answer better then me, and explain it if I'm on the right tack. BUT, my point is that I see nothng wrong. What does the first message box say?

[center][/center]Working on the next big thing.Currently Playing: Halo 4, League of LegendsXBL GT: iRememberYhslaw

Link to comment
Share on other sites

well, it is definitely wrong.

8.001 - 8 results 0.001 not 0.00099999999something

the first messagebox shows that int() is processed correctly, but afterwards the subtraction is definitely wrong.

try it with $x=8.0001. the result is wrong: 9.9999999999997669 e(-005)

????

Edited by jennico
Spoiler

I actively support Wikileaks | Freedom for Julian Assange ! | Defend freedom of speech ! | Fight censorship ! | I will not silence.OixB7.jpgDon't forget this IP: 213.251.145.96

 

Link to comment
Share on other sites

How many places did you want it rounded to? It's a floating point binary number to AutoIt (64bits, I think):

$x=8.001
Round($x-int($x), 14)
MsgBox(0,"To 14 places",String(Round($x-int($x), 14)))
MsgBox(0,"To 15 places",String(Round($x-int($x), 15)))

:)

Valuater's AutoIt 1-2-3, Class... Is now in Session!For those who want somebody to write the script for them: RentACoder"Any technology distinguishable from magic is insufficiently advanced." -- Geek's corollary to Clarke's law
Link to comment
Share on other sites

well, i know that i can round the result. but still the result before rounding is wrong. i used this operation in a program and couldn't find this error in several days.

8.0001 - 8 should return 0.0001 without rounding, or not ?

every cheap calculator does it right. (btw: the windows calculator does it, too)

j. :-)

Edited by jennico
Spoiler

I actively support Wikileaks | Freedom for Julian Assange ! | Defend freedom of speech ! | Fight censorship ! | I will not silence.OixB7.jpgDon't forget this IP: 213.251.145.96

 

Link to comment
Share on other sites

Like I said, It's how AutoIt handles the variables, somthing to do with variable type conversions I believe...

[center][/center]Working on the next big thing.Currently Playing: Halo 4, League of LegendsXBL GT: iRememberYhslaw

Link to comment
Share on other sites

try 8.0001-8.0 that should work at least i think :)

edit: nope sry tested it now dosen't work

Edited by alexmadman

Only two things are infinite, the universe and human stupidity, and i'm not sure about the former -Alber EinsteinPractice makes perfect! but nobody's perfect so why practice at all?http://forum.ambrozie.ro

Link to comment
Share on other sites

well, i know that i can round the result. but still the result before rounding is wrong. i used this operation in a program and couldn't find this error in several days.

8.0001 - 8 should return 0.0001 without rounding, or not ?

every cheap calculator does it right. (btw: the windows calculator does it, too)

j. :-)

Cheap calculators are just rounding to the display size, which is typically 10 digits. If you tell AutoIt to limit itself to 10 digits (by Round()), you get the same results as the cheap calculator.

:)

Valuater's AutoIt 1-2-3, Class... Is now in Session!For those who want somebody to write the script for them: RentACoder"Any technology distinguishable from magic is insufficiently advanced." -- Geek's corollary to Clarke's law
Link to comment
Share on other sites

maybe, but in this case it is a bug and i want to report it to the development team. should have to be fixed.

j.

@PsaltyDS: EVERY calculator does 8.0001-8=0.0001. this is a fact like 1+1=2. there is no need to round anything. it is a subtraction and not a division and a subtraction can not result indefinitely !!!!!!!!

Edited by jennico
Spoiler

I actively support Wikileaks | Freedom for Julian Assange ! | Defend freedom of speech ! | Fight censorship ! | I will not silence.OixB7.jpgDon't forget this IP: 213.251.145.96

 

Link to comment
Share on other sites

maybe, but in this case it is a bug and i want to report it to the development team. should have to be fixed.

j.

@PsaltyDS: EVERY calculator does 8.0001-8=0.0001. this is a fact like 1+1=2. there is no need to round anything. it is a subtraction and not a division and a subtraction can not result indefinitely !!!!!!!!

The thing you are missing is that the calculator and the computer are binary devices. They actually don't understand 8.0001 at all. The decimal number must be converted to a binary floating point first, and when that happens a rounding convention is applied. For a typical 32-bit CPU, the rounding convention is IEEE-754, which is accurate to about 16 decimal places. This is more than the "cheap" calculator probably uses. Look closely at the code I posted and you'll see that if the convention used has any less than 15 decimal places of precision, the result becomes as you expected. Cheap calculators have less than 15 decimal places of precision.

From Wikipedia: Floating Point

...the most common ways of representing floating-point numbers in computers are the formats standardized as the IEEE 754 standard, commonly called "IEEE floating-point". These formats can be manipulated efficiently by nearly all modern floating-point computer hardware, and this article will focus on them. The standard actually provides for many closely-related formats, differing in only a few details. Two of these formats are ubiquitous in computer hardware and languages:

* Single precision, called "float" in the C language family, and "real" or "real*4" in Fortran. It occupies 32 bits (4 bytes) and has a significand precision of 24 bits. This gives it an accuracy of about 7 decimal digits.

* Double precision, called "double" in the C language family, and "doubleprecision" or "real*8" in Fortran. It occupies 64 bits (8 bytes) and has a significand precision of 53 bits. This gives it an accuracy of about 16 decimal digits.

:)

Valuater's AutoIt 1-2-3, Class... Is now in Session!For those who want somebody to write the script for them: RentACoder"Any technology distinguishable from magic is insufficiently advanced." -- Geek's corollary to Clarke's law
Link to comment
Share on other sites

well, you want to explain why this error occurs. so good so fine.

but it is still a bug. autoit must be able to return the proper result like the windows calculator does.

so i would like to have this subtraction thing fixed in the next edition. it is better when the mathematical functions are reliable.

j.

Edited by jennico
Spoiler

I actively support Wikileaks | Freedom for Julian Assange ! | Defend freedom of speech ! | Fight censorship ! | I will not silence.OixB7.jpgDon't forget this IP: 213.251.145.96

 

Link to comment
Share on other sites

..but it is still a bug. autoit must be able to return the proper result like the windows calculator does.

:D:):ph34r::lmao::D:D:D

...whoo, give me a sec to catch my breath...

:P

That was a good one. You do understand that windows does its math the exact same way AutoIt does, and what you are describing is the ouput of ROUNDING THAT IS DONE IN THE CALC.EXE CODE, right?

:D

Valuater's AutoIt 1-2-3, Class... Is now in Session!For those who want somebody to write the script for them: RentACoder"Any technology distinguishable from magic is insufficiently advanced." -- Geek's corollary to Clarke's law
Link to comment
Share on other sites

no. you don't get the point.

you do know the result when you subtract 8 from 8.0001 ? right ?

it's definitely 0.0001 and nothing else. mathematics is a very strict science there is no way to discuss this result. so that is what i expect: getting the right result from the machine and not a "very close" result that can be rounded.

okay ?

j.

Spoiler

I actively support Wikileaks | Freedom for Julian Assange ! | Defend freedom of speech ! | Fight censorship ! | I will not silence.OixB7.jpgDon't forget this IP: 213.251.145.96

 

Link to comment
Share on other sites

The behavior is exactly the same as nearly every other programming/scripting lanauage out there. It is simply the result of how floating point numbers are handled. There are plenty of resources avialable on the topic and they all confirm the way autoit handles them. No bug.

Edit: Pentaly's link is good, also this one- http://www.regdeveloper.co.uk/2006/08/12/f..._approximation/ explains it well... i think you are under the mistaken impression that when you type 8 and 8.0001 you actually get those exact values when you compile...that is an absolute how to say... 'false-ity' :)

Edited by evilertoaster
Link to comment
Share on other sites

  • Moderators

Guess you could just make exceptions for the rule yourself...

$nNum = 8.001
$nSub = _CalcIt($nNum, Int($nNum), '-')
MsgBox(64, 'Info', $nSub)


Func _CalcIt($nNumber, $nNumber2, $vExecute = '+')
    If $vExecute <> '-' Then Return Number(Execute($nNumber & $vExecute & $nNumber2))
    Local $aDec = StringRegExp($nNumber, '.(\d+)', 1)
    Local $aDec2 = StringRegExp($nNumber2, '.(\d+)', 1)
    If IsArray($aDec) = 0 And IsArray($aDec2) = 0 Then _
        Return Number(Execute($nNumber & $vExecute & $nNumber2))
    If IsArray($aDec) Then $aDec = $aDec[0]
    If IsArray($aDec2) Then $aDec2 = $aDec2[0]
    Local $nTotal = Execute($nNumber & $vExecute & $nNumber2)
    Local $nSLNum = StringLen($aDec), $nSLNum2 = StringLen($aDec2)
    If $nSLNum > $nSLNum2 Then Return Number(Round($nTotal, $nSLNum))
    Return Number(Round($nTotal, $nSLNum2))
EndFunc

Edit:

Forgot a Return.

Edited by SmOke_N

Common sense plays a role in the basics of understanding AutoIt... If you're lacking in that, do us all a favor, and step away from the computer.

Link to comment
Share on other sites

okay okay.....

you are all right. floating points are like this and i can write simple functions to .....how to say.... correct (?) the correct results and improve the approximation.

this still is not satisfying because the machine (the script) does simple errors in simple operations that can cost a lot of time because you don't expect it. when u use a mathematical operation like "-" it would be nice to get a correct a result and not an approximation.

it would just be a little bit more user friendly to give out the rounded result and still the machine has to work for me and not i for the machine.

brave new world.

j. :-)

by the way: 8.0001-8=0.0000999999999999...

but: 80001-80000=1

the only difference is the floating point position..........

Spoiler

I actively support Wikileaks | Freedom for Julian Assange ! | Defend freedom of speech ! | Fight censorship ! | I will not silence.OixB7.jpgDon't forget this IP: 213.251.145.96

 

Link to comment
Share on other sites

no. you don't get the point.

you do know the result when you subtract 8 from 8.0001 ? right ?

it's definitely 0.0001 and nothing else. mathematics is a very strict science there is no way to discuss this result. so that is what i expect: getting the right result from the machine and not a "very close" result that can be rounded.

okay ?

j.

I really do see what you mean. It is very counter intuitive to say that 8.0001 - 8 = 0.000999999999999946 is accurate to a higher degree of precision than 8.0001 - 8 = 0.0001. Just remember that there are two instances of translation involved. From decimal to binary before the math, and binary to decimal after the math. Inside its code, where you don't see it, CALC.EXE gets the same result AutoIt does, because CALC was written in the same C++ code AutoIT was. Before showing it to you, to prevent confusion, CALC rounds off the answer and shows you 0.0001. You can have it either way with AutoIt. You can have the same answer that CALC get internally, or you can round it the same way and get the output.

Put another way, the difference between the AutoIt answer and the cheap calculator answer is 0.000000000000000054. If you tried to use the cheap calculator to show that, the error would be rounded to 0. So your cheap calculator agrees that there is no error.

BTW, you will only see this difference at very specific points in the number line. If 0.0001 decimal could be represented exactly in 64bit double precision binary floating point you would not have noticed the error. When you do the same trick with 8.00001 the "error" disappears. That's because 8.00001 can be represented in double float with greater precision than 8.0001 can. But the difference between the two is still smaller than a cheap calculator can display.

:)

Valuater's AutoIt 1-2-3, Class... Is now in Session!For those who want somebody to write the script for them: RentACoder"Any technology distinguishable from magic is insufficiently advanced." -- Geek's corollary to Clarke's law
Link to comment
Share on other sites

When you do the same trick with 8.00001 the "error" disappears. That's because 8.00001 can be represented in double float with greater precision than 8.0001 can.

sry, but 8.00001-8 results in the same error as 8.0001-8. so there is no logic.

But the difference between the two is still smaller than a cheap calculator can display.

this is a funny argument. in mathematics can never be differences ! there is just wrong or right. nothing else. 0 is not the same as 0.0000000000000000001. in any calculator.

It is very counter intuitive to say that 8.0001 - 8 = 0.000999999999999946 is accurate to a higher degree of precision than 8.0001 - 8 = 0.0001.

it is not counter intuitive, it's just WRONG.

furthermore, a subtraction or summing operation can never increase the number of decimal places. only division and multiplication can.

i understand the translation problem, but then it is badly solved.

as i said before: when 800001-800000 is 1 there can be no reason why 8.00001 - 8.00000 should not result in 0.00001. it seems to me that the floating point operation is buggy. why not turn the floating point variable into an integer by multiplication of a constant and then re-turn the result by division by the same constant ? there don't seem to be problems when calculating integers, while ANY decimal subtraction results in errors (even the simple 8.1-8.0 results in 0.099999999999999996).

so there's no reason for joking or arguing, it's just a simple bug.

j.

edit: since the developers here still find it correct, why not implement an option in future releases like

Opt("DecimalApproximationMode", 1) ;rounds the result ?

Edited by jennico
Spoiler

I actively support Wikileaks | Freedom for Julian Assange ! | Defend freedom of speech ! | Fight censorship ! | I will not silence.OixB7.jpgDon't forget this IP: 213.251.145.96

 

Link to comment
Share on other sites

I've encountered this already in c++. I was ready to type out a nice explanation on floating points as soon as I read the thread title but it seems that PSalty already has all the info down pretty nicely.

PSalty you know what they say about arguing on the internet....

I would advise you to give it up, no amount of logic or reason will do any good, he's already made up his mind that he is right and everyone else is wrong, regardless of how much more they know than him.

[font="Impact"] I always thought dogs laid eggs, and I learned something today. [/font]
Link to comment
Share on other sites

sry, but 8.00001-8 results in the same error as 8.0001-8. so there is no logic.

My mistake. I had an extra Round() in my test that didn't belong. This shows what we both mean:

Dim $avX[7] = ["", 8.1, 8.01, 8.001, 8.0001, 8.00001, 8.000001]
$Text = "$x - int($x)" & @CRLF
For $x = 1 To 6
    $Text &= "$x = " & $avX[$x] & @TAB & "No round = " & $avX[$x] - Int($avX[$x]) & @TAB & "Round to 14 places = " & Round($avX[$x] - Int($avX[$x]), 14) & @CRLF
Next
MsgBox(0, "$x - int($x)", $Text)

so there's no reason for joking or arguing, it's just a simple bug.

It's not a bug, it's just a difference between people and computers. When a person says 8.1 they mean with infinite zeros coming after. When a computer says 8.1 it means "rounded to number of bits in the registers of arithmetic logic unit". That leads to a difference you call "error", but remember the difference is less than 1e-14 in magnitude.

edit: since the developers here still find it correct, why not implement an option in future releases like

Opt("DecimalApproximationMode", 1) ;rounds the result ?

They might, but I hope they don't for the same reason I hope they never attempt to implement GOTO (And I'm pretty sure that'll never happen!). It leads to muddled thinking, bad practice, and sloppy code. A computer or script should always be programmed for the maximum possible accuracy, within the limits of its designed rounding error (64 bit floating point in our discussion). Only when the internal data is reformatted for human readability should such thing come into use, and that is fully accomplished by the Round() function already.

My only parting shot is to repeat that Excel formulas in Microsoft Office and CALC.exe do the same thing AutoIt does, and only pretend not to when they hide the Round() function that was done from you. If you don't want to see the Wizard, don't peek behind the curtain...

:)

Edited by PsaltyDS
Valuater's AutoIt 1-2-3, Class... Is now in Session!For those who want somebody to write the script for them: RentACoder"Any technology distinguishable from magic is insufficiently advanced." -- Geek's corollary to Clarke's law
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...