Results 1 to 15 of 15

Thread: Compounding Variables (Exceeding the max value for a 32-bit unsigned Int)

  1. #1
    Join Date
    Feb 2006
    Location
    Australia
    Posts
    628
    Mentioned
    15 Post(s)
    Quoted
    105 Post(s)

    Lightbulb Compounding Variables (Exceeding the max value for a 32-bit signed Int)

    This is a concept I discovered whilst working on RPS almost 10 years ago..
    So it's common knowledge at certain Java communities that the maximum value of a 32-bit signed integer is 2,147,483,647
    Why is this an issue? Well because in runescape, when you used to achieve that much exp, it was considered level 99 because they didn't know how to store all the values over that maximum number (2,147,483,647). It used to also affect the max stack for all items.
    I assume their immediate solution was to add more signed ints, so 10 would allow you to have 21,474,836,470 exp. This is not the best way to solve this problem as it could require 10 extra Ints for each skill for each player on the server.

    What I did for my system was create an interpreter before the number was displayed (client side), on the server side I would implement the other half of the interpretation system which worked like this:
    Simba Code:
    if (Int >  2,147,483,646) or (Int < LastValue) MaxInts++;
    Everytime the 32-bit signed int would breach max value, I would add 1 to my incremental int MaxInts
    This meant that I could still keep track of the value but it was quite hard to do any maths with the whole number. I used a binary-style interpretation technique to draw the numbers individually.. To explain it simply, I knew that the max value was 2,147,483,647 so if my MaxInts was 10, I would do 10x7 to display the last digit's multiplied value and work my way through, shortening the number so I could use math on it (remember all of the math has to be <= 2,147,483,647 or you will exceed the max value and lose data)

    TLDR; My method only requires 1 extra int per skill, to keep track of how many times the max value is exceeded.

    I thought I'd post this here since I haven't actually seen anything about it anywhere else and I was very interested to see other methods that people have used to combat this limitation. If anyone is curious, I can go into more detail and show better code examples of how to use this, just let me know.
    Last edited by Krazy_Meerkat; 02-04-2016 at 01:58 PM.

  2. #2
    Join Date
    Oct 2011
    Posts
    805
    Mentioned
    21 Post(s)
    Quoted
    152 Post(s)

  3. #3
    Join Date
    Feb 2012
    Location
    Norway
    Posts
    995
    Mentioned
    145 Post(s)
    Quoted
    596 Post(s)

    Default

    Quote Originally Posted by bg5 View Post
    Why can't you just change variable type to long (64-bit) ?
    Exactly, I am very curious to know why this was a no-no It could possibly be that he just wasn't aware of long, or that it's a 64 bit integer.
    Last edited by slacky; 02-04-2016 at 10:30 AM.
    !No priv. messages please

  4. #4
    Join Date
    Dec 2007
    Posts
    2,112
    Mentioned
    71 Post(s)
    Quoted
    580 Post(s)

    Default

    Quote Originally Posted by bg5 View Post
    Why can't you just change variable type to long (64-bit) ?
    Me, neither. Creative thinking though I guess.

  5. #5
    Join Date
    Dec 2013
    Location
    Pitcairn Island
    Posts
    288
    Mentioned
    20 Post(s)
    Quoted
    166 Post(s)

    Default

    Quote Originally Posted by Kasi View Post
    Me, neither. Creative thinking though I guess.
    I am also wondering this.

  6. #6
    Join Date
    Feb 2006
    Location
    Australia
    Posts
    628
    Mentioned
    15 Post(s)
    Quoted
    105 Post(s)

    Default

    Thanks for the replies, yes I was aware of long but it was a long time ago and I couldn't change the client-side variable type for a long reason.. *ohhhh*
    I did make the health variable type to long as a test, but it wouldn't compile and their client was still mostly obfuscated, I managed to find other instances which referenced the health value and expected a signed 32 bit int but there was a lot of them, after some amount of time I realised that I would have to basically rewrite a large portion (combat, items/effects, npcs, interfaces, scripted events, health checks, etc.) of the obfuscated client and server to use longs instead of ints.. I was not down with that. It was meant to be a simple test of changing 1 variable type, not hours of sorting through obfus code following the 32 bit ints and their usage with other 32 bit ints.. I might've encountered an issue with resources by adding so many longs instead of ints, I'm not too sure but I remember some issue with the JAR..

    TLDR; Problem was usage not declaration. Saved myself years worth of compile time.
    Last edited by Krazy_Meerkat; 02-04-2016 at 01:42 PM.

  7. #7
    Join Date
    Dec 2010
    Posts
    483
    Mentioned
    30 Post(s)
    Quoted
    328 Post(s)

    Default

    Quote Originally Posted by Krazy_Meerkat View Post
    Thanks for the replies, yes I was aware of long but it was a while ago and I couldn't change the client-side variable type for a long reason..
    I did make it long, but it wouldn't compile and their client was still mostly obfuscated, I managed to find other instances which referenced the health value and expected an unsigned 32 bit int but there was a lot of them, after some amount of time I realised that I would have to basically rewrite a large portion of the client and server to use longs instead of ints or I could do what I did.
    Okay so first of all...the maximum value of an unsigned integer is 4294967295. Not 2147483647 (which is the maximum of a signed integer).

    Second of all you can refactor the variable to long instead of just changing its type at declaration. That will remove the compile errors you are facing.

    EDIT:

    Worth considering some architectures simply have a long = int. Still though, a solution like this should never be necessary when we have 64 bit primitive types.

  8. #8
    Join Date
    Feb 2006
    Location
    Australia
    Posts
    628
    Mentioned
    15 Post(s)
    Quoted
    105 Post(s)

    Default

    Quote Originally Posted by the bank View Post
    Okay so first of all...the maximum value of an unsigned integer is 4294967295. Not 2147483647 (which is the maximum of a signed integer).

    Second of all you can refactor the variable to long instead of just changing its type at declaration. That will remove the compile errors you are facing.

    EDIT:

    Worth considering some architectures simply have a long = int. Still though, a solution like this should never be necessary when we have 64 bit primitive types.
    Hey man, I made a few edits but this happened 10 years ago and I hadn't actually heard of a free IDE at the time. Most private servers were batch compiled so I never even touched an IDE until much later.

    This solution works on any scale, the bank, I'm sure it will be useful to some.

    Signed int, my mistake.. I get confused in my old age

  9. #9
    Join Date
    Dec 2010
    Posts
    483
    Mentioned
    30 Post(s)
    Quoted
    328 Post(s)

    Default

    Quote Originally Posted by Krazy_Meerkat View Post
    Hey man, I made a few edits but this happened 10 years ago and I hadn't actually heard of a free IDE at the time. Most private servers were batch compiled so I never even touched an IDE until much later.

    This solution works on any scale, the bank, I'm sure it will be useful to some.

    Signed int, my mistake.. I get confused in my old age
    Ah fair enough, I was never a part of the RSPS scene and therefore wasn't aware of development conditions.

    Please don't mistake my comment of it not being necessary as it not being cool. This was some very creative thinking!

  10. #10
    Join Date
    Feb 2012
    Location
    Wonderland
    Posts
    1,988
    Mentioned
    41 Post(s)
    Quoted
    272 Post(s)

    Default

    Don't fully understand, but try to help nonetheless:
    https://villavu.com/forum/showthread.php?t=111841

    Edit: (looking for good reads, go to Brandon's user profile and find his started threads )

  11. #11
    Join Date
    Sep 2010
    Posts
    5,762
    Mentioned
    136 Post(s)
    Quoted
    2739 Post(s)

    Default

    Quote Originally Posted by Krazy_Meerkat View Post
    Hey man, I made a few edits but this happened 10 years ago and I hadn't actually heard of a free IDE at the time. Most private servers were batch compiled so I never even touched an IDE until much later.

    This solution works on any scale, the bank, I'm sure it will be useful to some.

    Signed int, my mistake.. I get confused in my old age
    omg remember when all the server/client files would be in 1 folder and client.java would be like 90% of the servers code?

    Now they are like, all organized and stuff

  12. #12
    Join Date
    Feb 2006
    Location
    Australia
    Posts
    628
    Mentioned
    15 Post(s)
    Quoted
    105 Post(s)

    Default

    Quote Originally Posted by rj View Post
    omg remember when all the server/client files would be in 1 folder and client.java would be like 90% of the servers code?

    Now they are like, all organized and stuff
    Lol, this is exactly what I remember..

    Thanks Le Jingle, that was more what I was thinking. Brandon did a really in-depth job, I like the fact that he made functions to change/compare the value.. I've stumbed across some nice threads by Brandon before, he could've gone into a bit more detail though, I see that he used a string to store the full value but I was wondering what Sign was for (pos/neg?) also there was a lot of reversing and memory shifting which I'm not really familiar with atm.. It's a nice looking class though
    Last edited by Krazy_Meerkat; 02-05-2016 at 05:18 AM.

  13. #13
    Join Date
    Dec 2007
    Posts
    2,112
    Mentioned
    71 Post(s)
    Quoted
    580 Post(s)

    Default

    Quote Originally Posted by Krazy_Meerkat View Post
    I was wondering what Sign was for (pos/neg?) also there was a lot of reversing and memory shifting which I'm not really familiar with atm.. It's a nice looking class though
    Not much memory shifting exists. Here's an example of why he's reversing, Imagine adding two numbers 125 + 75. Stored in string for 125 = {'1', '2', '5'}, 75 = {'0', '7', '5'};

    1 + 0 = 1,
    2 + 7 = 9,
    5 + 5 = 10. (Carry 1 where?)

    if these numbers were reversed. you could do;
    5 + 5 = 10 (Carry 1).
    2 + 7 + the Carry = 10. (Carry 1)
    1 + 0 + the Carry = 2.

    the string looks like "002". Reversed, it's 200. Similar concept applies to all the other methods. It's primarily done for the carry / borrow aspect.
    Last edited by Kasi; 02-05-2016 at 12:49 PM.

  14. #14
    Join Date
    Feb 2006
    Location
    Australia
    Posts
    628
    Mentioned
    15 Post(s)
    Quoted
    105 Post(s)

    Default

    Quote Originally Posted by Kasi View Post
    It's primarily done for the carry / borrow aspect.
    Ah that makes sense, thanks Kasi.

  15. #15
    Join Date
    Feb 2011
    Location
    The Future.
    Posts
    5,600
    Mentioned
    396 Post(s)
    Quoted
    1598 Post(s)

    Default

    Quote Originally Posted by Krazy_Meerkat View Post
    Ah that makes sense, thanks Kasi.
    Just a side note, if you don't want to use strings, you could actually store them as a series of integers and use bit manipulation

    http://stackoverflow.com/questions/4...r-classes?rq=1

    but for Simba, I can't see it helping that much. It's very rare that we need BigInt. Efficiency in Simba is usually not too much of an issue. We are using an interpreted language after all.

    But I agree with you. I could have written the better version of it but I was lazy lol. The difference between the two is pretty much reversing the numbers to do the carry vs shifting.

    If you use bits instead, then you just have to shift X amount of bits in order to store the new number. To speed up the BigInt, I instead decided to just store it in reverse anyway and then only when converting to string, I reverse it back. That way I don't have the overhead of reversing it every time I need to manipulate it.

    So there shouldn't be much of a difference in speed. The difference would be mostly Integer manipulation vs. char manipulation where the chars get up-padded to Ints on the bus (an extra operation) vs. Int's which are already 4 bytes and go easily.. and array resizing (With ints you resize 4 times less than using a char array but a good implementation would have a fixed size at the beginning anyway and resize via doubling capacity anyway).
    Last edited by Brandon; 02-06-2016 at 02:36 AM.
    I am Ggzz..
    Hackintosher

Thread Information

Users Browsing this Thread

There are currently 1 users browsing this thread. (0 members and 1 guests)

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •