PHP integer types



  • Not sure if this belongs under Coding Help or Sidebar WTF...

    I was reading up on integer types for PHP. I want item quantities in my MUD engine to use 64-bit integers, preferably unsigned, to avoid players hitting the limit. I used to play RuneScape and there were quite a few players who'd hit the limit with gold coins since it used signed 32-bit integers. They had to store wealth in something other than gold coins.

    Well MySQL supports UNSIGNED BIGINT so no big deal there.

    But PHP...

    Seems it doesn't have separate integer types, and the size of the integer is dependent upon your platform...? So if someone runs my MUD from a 32-bit OS, players could actually have overflow issues with item quantity. Not only that, but PHP apparently doesn't support unsigned integers. I could use floats, but floats and item quantities sounds like tons of odd bugs.

    Am I understanding this correctly?

    My host uses a 64-bit OS so I doubt I'll have any real problems using signed 64-bit ints...but still...WTF.



  • Wow, they made the same mistake C made in 1973. That's... kind of impressive.



  • Considering that PHP basically just wraps around C that's hardly surprising.



  • You are understanding it correctly.

    However... PHP 32-bit is surprisingly rare these days, and in actual fact you can bend the rules a little. The way floats work, you can actually safely hold something like 2^52-1 in a float without any loss of precision, which is generally sufficient precision for most things ;)

    Though if you have > 2.1bn items in a single player's inventory (which is where I would assume the issue would be anyway), I'd argue something else is wrong anyway.



  • @Arantor said:

    Though if you have > 2.1bn items in a single player's inventory (which is where I would assume the issue would be anyway), I'd argue something else is wrong anyway.

    This is most likely to happen with currency, like I said in the OP it happened all the time in RuneScape. I just want to be proactive.

    So, essentially I can use UNSIGNED BIGINT on the database end and just hope for the best? (really fighting the urge to physically facepalm right now.)



  • Well... I'd do all those operations in the database wherever possible anyway and try to avoid juggling between PHP and MySQL where possible.

    The other thing you can do is internally push everything to either the bc library or something like GMP which are internally arbitrary precision (at the cost of performance and ease of use), or even use strings just to ferry things around.

    It isn't PHP's finest hour for sure.



  • PHP doesn't really have "types" anyways, so this shouldn't be too much of a surprise. Not sure what a MUD engine is, but I'm guessing if you're running into this problem because you're trying to use PHP to build it I'm thinking that's TRWTF.

    Not that PHP isn't a WTF, oh no. It certainly is.


  • BINNED

    The obvious solution is, of course, to store digits into an array and then implode it for DB operations. For comparison you can just compare it digit by digit!

    *ducks*



  • @Onyx said:

    The obvious solution is, of course, to store digits into an array and then implode it for DB operations. For comparison you can just compare it digit by digit!

    ducks

    +💩



  • Now THERE's TRWTF.


  • BINNED

    Yeah... Sorry, I was in the Doing it Wrongâ„¢ mood still. I'm done now, I promise.

    On topic, it's not perfect but I think that the floating point solution is not that bad if you're really worried about the range. If you remember to floor it for any divisions it should work well enough.



  • The float solution is a dirty workaround but should theoretically be good even on 32 bit systems. Or it was when I researched it. Provided you stay below 2^52 or 2^53, I forget which it is, as your maximum value you're good.

    Useful in a tight spot, though.



  • Why don't you just re-write it in .NET?



  • Fortunately, it is extremely unlikely for your users to reach max_int (anything) and if they do, you're clearly doing it wrongtm.



  • @chubertdev said:

    Why don't you just re-write it in .NET?

    One of the major points of this project was to learn PHP since I've never dealt with it. I've been doing .NET for so long it's boring now.



  • RUN AWAY! RUUUUUUUUUNNNNNNN AAAAAAAWWWWWWWAAAAAAAAAAYYYYYYYYYYYYY!

    (sorry, there's nothing more appropriate than MP for this)



  • MP is appropriate for any situation.



  • Play with new and improved asp.net vnext on mono!

    It should have sufficient amount of new items to keep you busy, and theoretically it's supported.



  • I forgot about clans...each clan will have its own gold account and the clan leaders will be able to set a clan tax to help populate that account from any gold-making actions the members perform. I think that's the most likely scenario where item quantity could overflow using signed 32-bit ints.



  • @mott555 said:

    One of the major points of this project was to learn PHP since I've never dealt with it. I've been doing .NET for so long it's boring now.

    Because .NET Just Worksâ„¢?



  • It won't if you use a proper copper/silver/gold/platinum/diamond/whatever process.

    You create an exchanger that after they get past a certain amount, there's no room left to store money and they have to change the type of money for a small fee. It helps manage the economy and your bigint problem.



  • @Matches said:

    It won't if you use a proper copper/silver/gold/platinum/diamond/whatever process.

    You create an exchanger that after they get past a certain amount, there's no room left to store money and they have to change the type of money for a small fee. It helps manage the economy and your bigint problem.

    That's a possibility, but for simplicity's sake I wanted to stick with a single currency type. Also the currency is just like any other item except the MudSettings table holds the ItemClassID of which item counts as the game's currency.

    Also, I don't think I have a bigint problem, it looks like I can use signed 64-bit integers and that ought to be enough. I'm just partially concerned about hosting on 32-bit platforms, which I won't be doing but technically I have open-sourced the project so there's the possibility of someone else having problems with it.



  • Yea even the extensions are dumb but they can do 64-bit math.



  • Add something that checks if the platform is 32-bit, warns the admin about the problem and limits the amount of currency? Sometimes simple solutions are the best.

    Or use a custom big_integer class that stores a number as two ints and does the proper operations?



  • You should have split that into two posts so I could like the first part but not the second.


  • ♿ (Parody)

    @Arantor said:

    (sorry, there's nothing more appropriate than MP for this)

    Stop apologizing. Just enjoy the fact that your natural behavior works to troll certain precious snowflakes around here, where we're all trolls.


  • ♿ (Parody)

    @mott555 said:

    which I won't be doing but technically I have open-sourced the project so there's the possibility of someone else having problems with it.

    Now you've got this open source thing down.



  • @boomzilla said:

    Now you've got this open source thing down.

    Far better to just add it to the list of requirements for using your software. Eventually, when the requirements and dependencies get complicated enough, you'll be the only person that can understand it and will be able to charge people for hosting or installation. That way you can make money while extolling the open source nature of your product.


  • Discourse touched me in a no-no place

    .. that sounds.... strangely familiar..



  • @PJH said:

    .. that sounds.... strangely familiar..

    I don't know what you're talking about...

    >>
    <
    <
    >_>



  • @Arantor said:

    Though if you have > 2.1bn items in a single player's inventory (which is where I would assume the issue would be anyway), I'd argue something else is wrong anyway.

    @mott555 said:

    This is most likely to happen with currency, like I said in the OP it happened all the time in RuneScape. I just want to be proactive.

    Hint: Eve player speaking here.

    1. My main character's bank account hasn't fit into a signed 32bit int for years.
    2. Large stockpiles of crafting materials in Eve can easily exceed INT32_MAX items, due to the large quantities of basic materials demanded by large-scale manufacturing projects in that game. While I doubt that @mott555 will ever have to deal with Pandemic Legion cranking out capitals at a doomsday pace, you can't predict what your users will do.

    @Matches said:

    It won't if you use a proper copper/silver/gold/platinum/diamond/whatever process.

    Uh, no. Large entities will eventually run you out of currency denominations. Do I have to dig up PL's balance sheets for you?


  • ♿ (Parody)

    @tarunik said:

    Do I have to dig up PL's balance sheets for you?

    Yes, please.



  • Each item class has a base buy/sell value at standard shops, so IF signed 64-bit somehow ends up too small, I'll just make some high-valued items like a 10-billion gold coin or something. Can't directly buy and sell at shops with it, but you could with other players, and you can always sell it to a shop to get the straight 10bn gold coins.



  • There are many things wrong with PHP, but I count this among the minor ones. And understandable since taking a fixed size could cause all sorts of problems in interop with C, which PHP heavily leans upon. (e.g. if ints would be fixed at 32-bit the x86_64 version of PHP would probably have been delayed)

    It's not that big of a problem. You can easily check and warn with the PHP_INT_SIZE constant, or better yet use the arbitrary precision integer libraries that are available (which is often a good idea anyway when you work with such big numbers, since you can't accidentally convert them to floats and lose precision)



  • @mott555 said:

    IF signed 64-bit somehow ends up too small

    Are you recreating Cookie Clicker?



  • Well, distributing that stuff via Docker images only would solve the integer type issue, considering that Docker only seems to support 64-bit hosts and containers.


  • Discourse touched me in a no-no place

    @mott555 said:

    Seems it doesn't have separate integer types, and the size of the integer is dependent upon your platform...? So if someone runs my MUD from a 32-bit OS, players could actually have overflow issues with item quantity. Not only that, but PHP apparently doesn't support unsigned integers. I could use floats, but floats and item quantities sounds like tons of odd bugs.

    So make the system have a super-thief NPC that takes things from a user account once the number of items gets too large. If you're nice, start to give warnings beforehand about how having such large stockpiles can attract the unscrupulous from other dimensions…



  • @tarunik said:

    Hint: Eve player speaking here
    There's a reason Crowd Control Productions made an arbitrary precision math library in Perl for Eve, and that's because they knew what Eve's unique playerbase was likely to do. The same doesn't necessarily apply to Mott's friends.


  • BINNED

    @TwelveBaud said:

    because they knew what Eve's unique playerbase was likely to do

    You know, given their track record with players breaking shit and the responses...

    Can we get CCP to design forum software for us?

    Edit: Perl? Don't they script stuff in Python?



  • @TwelveBaud said:

    There's a reason Crowd Control Productions used Python's built-in bigint support [s]made an arbitrary precision math library in PerlPython[/s] for Eve, and that's because they knew what Eve's unique playerbase was likely to do. The same doesn't necessarily apply to Mott's friends.

    FTFY.
    I think they limit stack counts, currency, and inventory sizes by INT64_MAX, anyway, for DB storage reasons. (I know stack counts in Eve are signed due to mild hackery performed to deal with singleton items, and INT64_MAX bounds inventory sizes as well due to running the DB out of item IDs at the end of the day. You try to implement a DB that uses bigints as primary keys!)

    Edit: found a Discourse bug! Turns out it strips style attributes from HTML you insert, which makes it pretty darn well impossible to insert a double strikethrough into a post.


  • BINNED

    Screw you both! Now I want to re-subscribe! But I don't have the time for that damn game life sucker!



  • @Onyx said:

    But I don't have the time for that damn game life sucker!

    You're talking about Evony, right?



  • @redwizard said:

    You're talking about Evony, right?

    OMG that game sucked me in for a couple weeks and then once I hit the leaderboards I got attacked by all the world leaders every 20 minutes and literally couldn't do anything. And no that was not a misuse of the word literally.


  • ♿ (Parody)

    @tarunik said:

    You try to implement a DB that uses bigints as primary keys!

    What's the big deal? GUID keys are common enough.



  • @boomzilla said:

    tarunik said:
    You try to implement a DB that uses bigints as primary keys!

    What's the big deal? GUID keys are common enough.


    Well...you'd have to hash the bigints, just like using a string as a key, which loses you all the efficiency you gain from using an integer surrogate key. (UUID's are fixed length, so they don't suffer from this problem nearly as much unless some nitwit stores them as a varchar).


  • Discourse touched me in a no-no place

    @tarunik said:

    UUID's are fixed length
    So a CHAR(128) will do for them? Great!



  • @boomzilla said:

    GUID keys are common enough.

    Bud GUID is only globally unique. Doesn't cut it for the galaxy simulator.


    Filed under: ba-dum-tss



  • This post is deleted!


  • Are you coming on to me?


  • ♿ (Parody)

    @Maciejasjmj said:

    Bud GUID is only globally unique. Doesn't cut it for the galaxy simulator.

    You're right. Better switch to UUID. We can move on to MUIDs later.


Log in to reply