Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

How to display variables with consistent decimal places and also do math on them?

I've got a game with a wallet that keeps track of how much money the player has, and players can buy things in increments of 25 cents. However, I can't get the wallet to consistently display to two decimal places, so when the player has $1.50 it displays as $1.5.

I've tried using .toFixed(2):
(set: $money to (it-1.75).toFixed(2))

but then when the player tries to buy things they get an "undefined" error and the wall. It seems that these variables are being interpreted as strings instead of numbers, and that's why the math isn't working, so I tried using Number:
(set: $money to Number((it-1.75).toFixed(2)))

This does the math, but then it goes back to dropping the zeros on numbers like 1.50 (so I'm back to my original problem).

I'm working in Harlowe, and most of the discussion on decimal points seems to be in Sugarcube. Any folks working with decimal places in Harlowe have any advice?

Comments

  • My usual suggestion, regardless of story format, is to not use a floating point type, which is JavaScript's only decimal type, for currency. Due to rounding issues, caused by floating point's accuracy caveats, you can end up with odd results.

    I suggest tracking the lowest common denomination of currency in your world, which seems to be cents in this case, and only converting to dollars when printing for the player.

    So, for example, to set $money to $2.50:
    (set: $money to 250)
    
    And to subtract $1.70 from that:
    (set: $money to it - 170)
    


    To make printing cents out in dollars for the player easier, I'd suggest setting up a function to handle it. For example, add something like the following to your Story JavaScript:
    window.asDollars = function (cents) {
    	return '$' + Number(cents + 'e-2').toFixed(2);
    };
    
    And using it:
    <!-- Assuming $money is 80, prints: $0.80 -->
    (print: asDollars($money))
    
  • Ahh, thanks very much! Will try that.
  • Nice feature :) And very easily pluggable. Is there a way to modify it so when you generate how much you 'start' with, using this function - to always have .00 cents? To make it always in terms of dollars, generating 20.00, rather than 42.44 at random?
  • Gryphbear wrote: »
    Is there a way to modify it so when you generate how much you 'start' with, using this function - to always have .00 cents? To make it always in terms of dollars, generating 20.00, rather than 42.44 at random?
    Either you're misunderstanding something or I am. The asDollars() function does nothing randomly.

    The whole point of my previous original reply is that you cannot depend upon floating point numbers for exact accuracy, so in cases where you want/need it—e.g. with currency—don't use floating point numbers. In this case the suggestion was to simply track the player's money via the lowest common denomination, cents, so that whole/integer numbers could be used.

    All the asDollars() function does is to take a given number of cents and return a string representation of the equivalent number of dollars and cents—format: $#+.##. It accomplishes this by shifting the decimal place using the Stupid Scientific Notation Trick™—it does not use division, so as to avoid floating point conversation.

    If you've tried the function and are seeing results like $42.44, then you've passed it something which would generate that representation—e.g. 4244.

    Could you clarify your question?
  • In my project - I'm generating a random 'amount' of cash to start with for my character. It was <<set $cash to random(20, 60)>>, but since I saw your function just in this thread, I thought I'd see if I could generate an actual 'dollar' output rather than having to simulate the fact the character has money. (Basically - only having the first two digits between 20-60 'bucks')

    I was just wondering if it were possible to make it only output the dollar parts, plus .00 cents. (Since my character is wearing a wallet, without really any room for spare change).

    That's why I set my <<set $cash to random(2000, 6000)>> in the first place, but I didn't actually realize that it'd pick random cents, as well ;)
  • edited January 2017
    Using cents as the tracked value, do the following:
    <<set $cash to random(20, 60) * 100>>
    


    Alternatively, since you only wish to track whole dollars, just do that. If you want to print the player's money in dollars & cents format, even though you're only using dollars, just do something like the following:
    <<print '$$' + $money + '.00'>>
    
    Turning that into a widget or function would be trivial, if desired.
  • edited January 2017
    AH. Cool Thanks. :) The first method works great. That's what I was looking for.
Sign In or Register to comment.