electro-music.com   Dedicated to experimental electro-acoustic
and electronic music
 
    Front Page  |  Radio
 |  Media  |  Forum  |  Wiki  |  Links
Forum with support of Syndicator RSS
 FAQFAQ   CalendarCalendar   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   LinksLinks
 RegisterRegister   ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in  Chat RoomChat Room 
 Forum index » DIY Hardware and Software » ChucK programming language
Strange mathematical behaviour in ChucK
Post new topic   Reply to topic Moderators: Kassen
Page 1 of 1 [14 Posts]
View unread posts
View new posts in the last week
Mark the topic unread :: View previous topic :: View next topic
Author Message
Dr. Spankenstein



Joined: Mar 03, 2007
Posts: 136
Location: Cambridge
Audio files: 1

PostPosted: Fri May 18, 2007 8:29 am    Post subject: Strange mathematical behaviour in ChucK Reply with quote  Mark this post and the followings unread

Can anybody explain why chuck will tell me that:

0.83 == 0.83

yet

1.333333 != 1.333333

I'm finding it incredibly infuriating! It happens when I'm performing the calculation many times per second (sorry for being a little vague)
Back to top
View user's profile Send private message
Kassen
Janitor
Janitor


Joined: Jul 06, 2004
Posts: 7678
Location: The Hague, NL
G2 patch files: 3

PostPosted: Fri May 18, 2007 9:16 am    Post subject: Reply with quote  Mark this post and the followings unread

Oh, dear oh, dear, oh dear! That sounds odd.

I ran a quick test;
Code:

if (1.333333 == 1.333333 ) <<<"yeah">>>;
else <<<"oops">>>;


And I get a "yeah" there. Could you give a example where ChucK messes this up? I gather this behaviour occurs in a more complicated setup? Likely it's a rounding error that you're suffering from, if it only uccors when calculating something "many times per second" it might also be a subtle timing issue?

Basically; could you write a program that's a simple as possible yet still has this error?

_________________
Kassen
Back to top
View user's profile Send private message Send e-mail Visit poster's website
Dr. Spankenstein



Joined: Mar 03, 2007
Posts: 136
Location: Cambridge
Audio files: 1

PostPosted: Fri May 18, 2007 9:31 am    Post subject: Reply with quote  Mark this post and the followings unread

I am willing to e-mail you my code but then again it would mean having to traipse through it.

If you dont mind then I dont mind! Smile

Theres a around 600 lines of the stuff tho.....

I honestly cant think of a way around it as it is very specific to the code. The problem arises when calculations are done very quickly ...or in this case the tempo has increased.

Rhys

PS. I have just got around it by adding a seperate counter that does the action and avoids the aforementioned error. Its a bodge job but it works.
Back to top
View user's profile Send private message
Kassen
Janitor
Janitor


Joined: Jul 06, 2004
Posts: 7678
Location: The Hague, NL
G2 patch files: 3

PostPosted: Fri May 18, 2007 9:43 am    Post subject: Reply with quote  Mark this post and the followings unread

Could you considder stripping this program down to the elements that generate this equation? Right now I suspect it's a rounding issue but rounding shouldn't be affected by tempo, that's quite mysterious. If that's realy the case Ge will have to look at it but chances are Ge too will sugest simplifying the code to the most simple form that still has the issue.

Another posibility is that when tempo increases the timing relation between multiple shred will change which might cause issues.

If you realy can't strip it; sure, mail it (adress is above my posts) but if it's 600lines I'm not making promisses about disecting it quickly :¬)

_________________
Kassen
Back to top
View user's profile Send private message Send e-mail Visit poster's website
Dr. Spankenstein



Joined: Mar 03, 2007
Posts: 136
Location: Cambridge
Audio files: 1

PostPosted: Fri May 18, 2007 10:18 am    Post subject: Reply with quote  Mark this post and the followings unread

I gonna carry on with the bodge job versiob for the time being. I will need quite some time to figure out how it could be scaled down. If I find a way I'll let you know.

Thanks again for your help

Rhys
Back to top
View user's profile Send private message
spencer



Joined: Aug 16, 2006
Posts: 53
Location: northern california

PostPosted: Mon May 21, 2007 12:19 pm    Post subject: Reply with quote  Mark this post and the followings unread

Hi Rhys,
You've actually come upon a fundamental limitation of computing in general, and binary real number data representation in particular. Floating point numbers are represented as the sum of positive and negative powers of 2, e.g. 2.125 = 2 + 1/8 = 2^1 + 2^-3 = binary 10.001. However, just like numbers such as 1/7 can't be represented exactly in finite-precision decimal, there are plenty of real numbers within the range of representable values that can't be represented exactly in finite-precision (aka digital) binary. So there's always a danger when comparing floating point numbers that the conversion from a decimal number in your code to the binary number in the CPU will have a rounding error that makes it different than the number to which you are comparing it. For a minimal example of this, try this code:
Code:
if( 4.0/3.0 != ( 4.0 * 5.2 * 5.2 * 5.2 ) / ( 3.0 * 5.2 * 5.2 * 5.2 ) )
    <<< "rounding error", "" >>>;

The two expressions are legitimately equal, but the computer thinks they are different. Converting each decimal number to binary and then doing different calculations on them introduces enough rounding error to make them different numbers in binary representation. The solution is to ignore the rounding errors and only determine if the two numbers are equal up to some decimal place:
Code:
if( Math.fabs( ( 4.0/3.0 ) - ( 4.0 * 5.2 * 5.2 * 5.2 ) / ( 3.0 * 5.2 * 5.2 * 5.2 ) ) > 0.000001 )
    <<< "not equal", "" >>>;

Here, ChucK (and basically any other program executing this expression on a similar architecture to mine) correctly identifies the two sides of the comparison as equal.

I might be a little shaky on the theory but the gist of all this should be right.

Long story short: dont compare floats directly. Instead, compare the absolute value of their difference to some relatively small value.

spencer

Last edited by spencer on Mon May 21, 2007 5:05 pm; edited 1 time in total
Back to top
View user's profile Send private message
kijjaz



Joined: Sep 20, 2004
Posts: 765
Location: bangkok, thailand
Audio files: 4

PostPosted: Mon May 21, 2007 1:54 pm    Post subject: Reply with quote  Mark this post and the followings unread

Wow! thanks spencer!
that explains how it happen really clearly..
at least for a non-professional-programmer like me.

cool and thanks.
Back to top
View user's profile Send private message Send e-mail Visit poster's website Yahoo Messenger MSN Messenger
Kassen
Janitor
Janitor


Joined: Jul 06, 2004
Posts: 7678
Location: The Hague, NL
G2 patch files: 3

PostPosted: Tue May 22, 2007 2:36 am    Post subject: Reply with quote  Mark this post and the followings unread

Seconded; good stuf.
_________________
Kassen
Back to top
View user's profile Send private message Send e-mail Visit poster's website
Dr. Spankenstein



Joined: Mar 03, 2007
Posts: 136
Location: Cambridge
Audio files: 1

PostPosted: Tue May 22, 2007 3:02 am    Post subject: Reply with quote  Mark this post and the followings unread

Brilliant!

Thanks for your clear insight Spencer you have been a great help to me and no doubt a lot of other people who might encounter this frustrating positive error.

I shall get implementing your thoughts on the solution right away!

Rhys
Back to top
View user's profile Send private message
Dr. Spankenstein



Joined: Mar 03, 2007
Posts: 136
Location: Cambridge
Audio files: 1

PostPosted: Tue May 22, 2007 5:10 am    Post subject: Reply with quote  Mark this post and the followings unread

I think I may have been a little hasty with my reply as I dont seem to fully grasp what is going just yet.

I figured that if I wanted to avoid rounding error that I could multiply the reoccuring decimal by a power of 10 and then find the absolute value and compare that to the other value that had gone through the same processes however, this doesnt work?

Code:


<<<Math.fabs((0.33333333)*1000000)>>>;
// Returns a number

<<<Math.fabs((1/3)*1000000)>>>;
// Returns 0.000000, why?!



Can anyone tell me where I'm going wrong?

Thanks again

Rhys
Back to top
View user's profile Send private message
chuckles



Joined: Apr 02, 2007
Posts: 72
Location: San Diego, California

PostPosted: Tue May 22, 2007 8:10 am    Post subject: Reply with quote  Mark this post and the followings unread

Quote:
<<<Math.fabs((1/3)*1000000)>>>;
// Returns 0.000000, why?!

I think it's still because of the "int" vs. "float" thing...

1/3 is .33333. But since they are both ints, the result is an int which, rounded, is 0. So multiplying that gives 0.

but 1./3 (and probably 1/3.) gives .33333 since one operand is a float and chuck does the calculation as floatingpoint.

at least that's how it looks from here...

c.
Back to top
View user's profile Send private message
kijjaz



Joined: Sep 20, 2004
Posts: 765
Location: bangkok, thailand
Audio files: 4

PostPosted: Tue May 22, 2007 8:36 am    Post subject: Reply with quote  Mark this post and the followings unread

you can also cast an int to float
by using $ float just behind what you want to convert.

for example

1 => int x;
<<< x / 3 >>>; // this is like 1/3
<<< x $ float / 3 >>>; // this would be 1.0 / 3, thus having a float result

<<< x * 1.0 / 3 >>>; // multiplying an int by a float also creates a float result
<<< 1.0 * x / 3 >>>;

<<< (x * 5.0 / 3) $ int >>>; // but we can convert back to int also
Back to top
View user's profile Send private message Send e-mail Visit poster's website Yahoo Messenger MSN Messenger
Dr. Spankenstein



Joined: Mar 03, 2007
Posts: 136
Location: Cambridge
Audio files: 1

PostPosted: Tue May 22, 2007 10:48 am    Post subject: Reply with quote  Mark this post and the followings unread

Ah dammit, I was hoping that werent the case. Using math.fabs doesnt work for my code as it still says they are not equal.

However, I found another nifty way that gets around this rounding error

Code:


if (Math.round(CurrentTime $ float * 1000000) == Math.round(DurationOfOneBar $ float * 1000000))



Multiplying each float by a factor of 10 depending on how accurate you want it to be then rounding to the nearest whole number does the trick!

Hope this helps anyone who might encounter this problem and once again, thanks for all your help guys.

Rhys
Back to top
View user's profile Send private message
Kassen
Janitor
Janitor


Joined: Jul 06, 2004
Posts: 7678
Location: The Hague, NL
G2 patch files: 3

PostPosted: Tue May 22, 2007 2:04 pm    Post subject: Reply with quote  Mark this post and the followings unread

Cool trick, I have to warn that there is a small theoretical risk though.

What could theoretically happen is that the two values to be compared somehow end up on oposite sides of the line that devides wether we round up or down.

If Spencer's methopd fails then this is likely because you are performing your operations in such a way that you get relatively large rounding errors so you might need to increase the difference that can be between your two numbers.

On the bright side; the very high presision floats that ChucK uses are quite nice to have for many applications.

_________________
Kassen
Back to top
View user's profile Send private message Send e-mail Visit poster's website
Display posts from previous:   
Post new topic   Reply to topic Moderators: Kassen
Page 1 of 1 [14 Posts]
View unread posts
View new posts in the last week
Mark the topic unread :: View previous topic :: View next topic
 Forum index » DIY Hardware and Software » ChucK programming language
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
You cannot attach files in this forum
You can download files in this forum


Forum with support of Syndicator RSS
Powered by phpBB © 2001, 2005 phpBB Group
Copyright © 2003 through 2009 by electro-music.com - Conditions Of Use