Register to post in forums, or Log in to your existing account
 

Play RetroMUD
Post new topic  Reply to topic     Home » Forums » CMUD General Discussion
shalimar
GURU


Joined: 04 Aug 2002
Posts: 4692
Location: Pensacola, FL, USA

PostPosted: Tue Mar 01, 2011 9:14 am   

1/100th is too precise?
 
In the below example, skills are represented on a scale of 0.00-100.00.

Is there a reason why $change will not show having a value of 0.01?

Code:
<trigger priority="200" repeat="true" id="1">
  <pattern>([%s%w]) (%d.%d)</pattern>
  <value>$skill=%trim(%1)
$level=%2
$change=%float($level)-%float(@skills.$skill)
#IF ($change) {#PRINT {Increase! $change in $skill}}
#ADDKEY skills {$skill=$level}</value>
</trigger>


The following two statements have different answers, so the bug is not even consistently displaying wrong.

#SAY %float(11.23-11.22)
#SAY %float(23.63-23.62)
_________________
Discord: Shalimarwildcat
Reply with quote
chamenas
Wizard


Joined: 26 Mar 2008
Posts: 1547

PostPosted: Tue Mar 01, 2011 12:29 pm   
 
I noticed something odd where after, say, 4 or so decimal places, it begins to try and store the values in scientific number form, at least in database records, which was extremely aggravating to deal with. I've no idea why it's having issues with two decimal places though.
_________________
Listen to my Guitar - If you like it, listen to more
Reply with quote
Rahab
Wizard


Joined: 22 Mar 2007
Posts: 2320

PostPosted: Tue Mar 01, 2011 1:38 pm   
 
The answer is in the nature of floats. Floats are not exact. You probably already know this. Due to the binary nature of floats in the computer, there is a slight error when translating a decimal float into binary. Then, when doing arithmetic calculations which in decimal appear equivalent, the error in the binary values results in very tiny differences in the result. In your example, %float(11.23-11.22) might result in 0.009999999...99, while %float(23.63-23.62) might result in 0.10000000...01 (examples only--the actual values will be different, and may even be different on different computers!). Comparing these numbers will then show them not to be equal. This is true in all programming languages, and is an inherent limitation on using floats. This is why many languages have an 'approximately equal to' operator for floats.

To solve this, you will have to change them out of floats. Multiply the values by 100, round off, and convert to int for your comparison.
Reply with quote
Erasmus
Wanderer


Joined: 04 Aug 2004
Posts: 82
Location: Philadelphia

PostPosted: Tue Mar 01, 2011 2:15 pm   
 
Don't know if this will work, but you could also try putting the %norm() function around your calculation.
I.e:
#SAY %norm(%float(11.23-11.22))
#SAY %norm(%float(23.63-23.62))
_________________
Erasmus
Reply with quote
shalimar
GURU


Joined: 04 Aug 2002
Posts: 4692
Location: Pensacola, FL, USA

PostPosted: Tue Mar 01, 2011 2:40 pm   
 
Yet calculators get around these limitations on a daily basis...
Finding a kludge for this error is simple enough...
But i don't want to have to have my code doing tricks and flipping the numbers just to show 0.01 - this is BASIC math, CMUDPro should be capable of this
_________________
Discord: Shalimarwildcat
Reply with quote
Rahab
Wizard


Joined: 22 Mar 2007
Posts: 2320

PostPosted: Tue Mar 01, 2011 5:17 pm   
 
Calculators do _not_ get around these limitations. Calculators round things off when they display the results to you. The limitations only show up when you use comparison operators, or other things that calculators do not have. This is basic math in the decimal world, but it is _not_ a trivial problem when dealing with floats in the binary world. As I said, all programming languages have this problem. It is fundamental to binary floats. How do you suggest that the problem be solved?

As an example:
Code:

11.23 in binary:  1011.00111010111000010100011110101110...
11.22 in binary:  1011.00111000010100011110101110000101...
Difference:          0.00000010100011110101110000101001...
0.01 in binary:      0.00000010100011110101110000101000...

Converting the binary values above to decimals:
11.23:      11.229999999981374
11.22:      11.21999999997206
Difference:  0.0100000000093132
0.01:        0.00999999977648258

How do you expect Cmud (or any other programing language) to know that the difference should be precisely 0.01? All the program knows is binary. As I said before, this is a fundamental problem of using binary floats. It simply cannot recreate decimal values with precision.
Reply with quote
Zugg
MASTER


Joined: 25 Sep 2000
Posts: 23379
Location: Colorado, USA

PostPosted: Tue Mar 01, 2011 5:46 pm   
 
Quote:
CMUDPro should be capable of this

This is why CMUD gives you the %round function and the %norm function. Use them.

CMUD already handles these floating point issues when performing comparisons between numbers (such as #IF (@a = @b) ...)

These are not kludges. As Rahab mentioned, this is the case in ANY programming language, not just zScript. It's something you learn to deal with in Programming 101 class.

Also, CMUD isn't a calculator.
Reply with quote
Rahab
Wizard


Joined: 22 Mar 2007
Posts: 2320

PostPosted: Tue Mar 01, 2011 6:09 pm   
 
I'd forgotten that Cmud automatically norms floats in comparison operations. Puts it one up on a lot of programming languages!
Reply with quote
MattLofton
GURU


Joined: 23 Dec 2000
Posts: 4834
Location: USA

PostPosted: Tue Mar 01, 2011 11:05 pm   
 
Quote:

Also, CMUD isn't a calculator.


You perhaps didn't aim for that goal, but I'll have you know that CMud is the mother of all calculators in my eyes. If I ever have to go to a calculator website or open up the Calculator utility in Windows, I always turn to CMud instead and use that (or spend the time building a new function or whatever so that I can use CMud the next time).
_________________
EDIT: I didn't like my old signature
Reply with quote
shalimar
GURU


Joined: 04 Aug 2002
Posts: 4692
Location: Pensacola, FL, USA

PostPosted: Wed Mar 02, 2011 9:10 pm   
 
Well.. %norm doesn't seem to change the data much at all
%round only returns integers.

Essentially you are telling me there is no way to do this precisely without converting it to integer math?

A calculator may be doing all these tricks inside its (incredibly small and weak) computer mind, but i bet i can punch in 22.33 - 22.32 and get 0.01 regardless of brand or age.

P.S. I did find a way, although I don't see why it needs me to tell it to do this: %format(&3.2f, $change)

P.S.S. Granted, i only program as a hobby... but i always just inherited someone else's math code into my programs, so I never noticed issues with floating point math.. it just never came up.
_________________
Discord: Shalimarwildcat
Reply with quote
Rahab
Wizard


Joined: 22 Mar 2007
Posts: 2320

PostPosted: Wed Mar 02, 2011 9:27 pm   
 
Quote:
A calculator may be doing all these tricks inside its (incredibly small and weak) computer mind, but i bet i can punch in 22.33 - 22.32 and get 0.01 regardless of brand or age.

That is only because the calculator only shows a small fraction of the number of digits it actually calculates values to. In other words, it rounds it off. It will never show you those last 30 digits (or whatever), where the discrepancy shows up. It doesn't even try to _remember_ those last digits after the calculation is done. It does the calculation out to X digits (say, the decimal equivalent of 100), converts it to decimal, rounds it off (say, to 50 digits), stores that value in its register, and displays the result. Floats on a computer don't work that way. Float mathematics depends on the low-level operations within the computer chip itself, beyond the reach of any programming language. This is why different chips can actually produce different values in the nth digit in float calculations. To simulate in Cmud or another programming language what a calculator does, you use %format, as you described above.
Reply with quote
shalimar
GURU


Joined: 04 Aug 2002
Posts: 4692
Location: Pensacola, FL, USA

PostPosted: Wed Mar 02, 2011 9:34 pm   
 
#SAY %norm(%float(11.23-11.22))
0.00999999977648258

#SAY %format(&3.2f, %float(11.23-11.22))
0.01

#SAY %format(&3.9f, %float(11.23-11.22))
0.010000000

Once i format it, regardless of the decimal precision i ask for, it always gives 0.01.
Should not the 9 decimal precision show 0.009999999, given the unformated value?
Granted... i like seeing the true value, but i don't understand why the results are changing.
//Nevermind, it is rounding to the decimal here instead of truncating as &3.13f shows.
_________________
Discord: Shalimarwildcat
Reply with quote
shalimar
GURU


Joined: 04 Aug 2002
Posts: 4692
Location: Pensacola, FL, USA

PostPosted: Wed Mar 02, 2011 9:50 pm   
 
After a bit of research I came across this...

The "decimal" data type of the C# and Python (programming language), and the IEEE 754-2008 decimal floating-point standard, are designed to avoid the problems of binary floating-point representations when applied to human-entered exact decimal values, and make the arithmetic always behave as expected when numbers are printed in decimal.

Is there an equivalent in perl that could be added to CMUD?
_________________
Discord: Shalimarwildcat
Reply with quote
Zugg
MASTER


Joined: 25 Sep 2000
Posts: 23379
Location: Colorado, USA

PostPosted: Thu Mar 03, 2011 5:15 pm   
 
I have no plans to add a "decimal" type to CMUD, sorry. That would be a huge amount of work.

%norm "fixes" the numbers so that they can be properly compared by ensuring that the last few significant digits are rounded.

I might add an argument to %round in the future to specify the number of decimal places to round to.
Reply with quote
shalimar
GURU


Joined: 04 Aug 2002
Posts: 4692
Location: Pensacola, FL, USA

PostPosted: Fri Mar 04, 2011 8:27 am   
 
I actually tried throwing in a ,2 when testing it out, just to see if that was an undocumented feature. That would be a quite useful addition.
_________________
Discord: Shalimarwildcat
Reply with quote
Display posts from previous:   
Post new topic   Reply to topic     Home » Forums » CMUD General Discussion All times are GMT
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum

© 2009 Zugg Software. Hosted by Wolfpaw.net