views:

455

answers:

5

I'll try to explain this problem the best way i can with code:

double power = 5000;
//picked up 5 power ups, now need to increase power by 10% per powerup
power += 5 * (power * .10);


//later on...ran into 5 power downs need to decrease power back to initial hp
power -= 5 * (power * .10);//7500 - 3750 -- doesn't work

So what i need is a scaleable solution that gets back to the original value using only the count. Any ideas?

+1  A: 

I'm going to suspect that what you mean by "doesn't work" is that the value for power does not end up to be exactly 3750.

This is due to floating-point rounding errors, as floating point values such as double and float are not able to be represented exact values.

If exact values are needed, then using decimal or int would be a better solution, as they are designed to handle exact values.

Edit The actual issue here is not a floating-point rounding error, but an issue noted in Smashery's answer.

coobird
No, I think the problem here is that if you add 10% and then subtract 10%, you get 99% of your original value. 1 + 10% = 1.1 and then 1.1 * 90% = 0.99
Smashery
Ah, you're right Smashery, that seems to be the issue here.
coobird
+15  A: 

The best way to do this is using a function. It doesn't have to look exactly like this, but:

class Whatever
{

    private double basePower = 5000;

    public int numPowerUps = 5;

    public double GetActualPower()
    {
        return basePower + (numPowerUps * basePower * 0.1);
    }
}

Just change numPowerUps back to 0 when they run out. This way, it looks a whole lot neater.


An aside:
The reason it's not working is because of the fact that adding and then subtracting percentages doesn't work. For instance:

1. What is 10% of 100?    --> 10
2. Add that to the 100    --> 110
3. What is 10% of 110?    --> 11
4. Subtract that from 110 --> 99

You'll always end up with 99% of your original value. If you really want to take a shortcut, you could instead do this:

1. What is 10% of 100?    --> 10
2. Add that to the 100    --> 110
3. What is (100/11) = 9.09090909...% of 110?    --> 10
4. Subtract that from 110 --> 100

But then you're potentially susceptible to floating point errors. The function way of doing it is not only neater and clearer, but potentially less error-prone.

Smashery
Your comment to coobird's post is exactly the problem i'm trying to remedy.
cellis
@cellis5078 - The best way of doing this is by remembering what it should go back to by storing that *and not changing it*. And when you want to see what the "powered-up" value is, do the calculation then. That's good for several reasons: It's neater, it's impossible to lose track of how many power-ups they have (since you're storing that too), and it's not going to have floating point errors.
Smashery
+1, good explanation
David Schmitt
+2  A: 

This doesn't work because the two percentages are not taken from the same number. They're taken from the same variable, but not the same number.

The first time, power * 0.10 is 500, and 5*500=2500 so the power will be 5000+2500=7500. Now, the power is 7500, so power * 0.10 is 750. 5*750 = 3750 and 7500-3750=3750 and not 5000 like you started out with.

So apparently, what you want is not really to in/decrease by a percentage of the current power. Perhaps it would be better to set a base power (let's say 5000) and an actual power. Then when you in/decrease, you use actualPower = actualPower + 5*0.1*basePower; or something. Or you just accept that five power downs after five power ups does not get you back to initial hp.

Jordi
+3  A: 

To reverse a %age increase, you must divide by the original %age, not subtract.

i.e.:

100 + 5% = 100 * 1.05 = 105

to reverse it:

105 / 1.05 = 100

The more usual '5% off' formula would instead give you:

105 - 5% = (105 * 0.95) = 99.75
Alnitak
+4  A: 

To power up:

power <- power * (1 + count * percent);
eg: 5000 * (1 + 5 * 0.1)
    5000 * 1.5
    7500

To power back down:

power <- power / (1 + count * percent)
eg: 7500 / (1 + 5 * 0.1)
    7500 / 1.5
    5000

Let's take a more complicated example, 17 power ups, each giving 3% to an intial 1234 power:

  1234 * (1 + 17 * 0.3)
= 1234 * (1 + 5.1)
= 1234 * 6.1
= 7527.4

  7527.4 / (1 + 17 * 0.3)
= 7527.4 / (1 + 5.1)
= 7527.4 / 6.1
= 1234

It actually looks pretty simple when you write it out like that.

paxdiablo