Erik Funkenbusch
Erik Funkenbusch

Reputation: 93434

Help optimizing algorithm

I have a particular application that needs to calculate something very specific, and while I excel at logic, math has always been my weak spot.

Given a number, say -20, it needs to apply a calculation of a 100 base (that is, the base is 100, not 0. not to be confused with base 100 which would be something else totally).

In other words, the math works like this ..., 105, 104, 103, 102, 101, 100, -101, -102, -103, -104, -105, ...

Then I need to do the math based on this 100 base figure.

So, for example:

-140 - 20 =  120
-120 - 20 =  100  
-115 - 20 = -105
-110 - 20 = -110
-105 - 20 = -115
 100 - 20 = -120  
 120 - 20 = -140

If it helps, the problem is related to sports odds. In theory, this refers to money (risk $1.40 to win $1.00 on one side, risk $1.00 to win $1.20 on the other, the .20 difference is what casinos call "the juice" or their cut of moving money back and forth.) However, the program is not dealing with real money, it's more of a simulator.

My current formula works like this:

decimal CalculateSides(decimal side, decimal vig)
{
    decimal newSide = side - vig;

    newSide = -(newSide < 0) ? newSide + 100 : newSide - 100;

    return (newSide < 0) ? newSide + 100 : newSide - 100;
}

While this formula works, I'm not very happy with the conditional +/-, but this is basically the only formula that works for me.

Can anyone suggest a way to improve this? Preferably without conditions of +/-?

EDIT:

When I asked the question, I knew one possible answer was "It's probably best the way you're doing it", and that seems to be the consensus.

Upvotes: 1

Views: 290

Answers (4)

vaab
vaab

Reputation: 10122

The 'sign' solution could be more elegant:

decimal CalculateSides(decimal side, decimal vig)
{
    decimal res = side - vig  +  (100 * Math.Sign(side));
    return  res               +  (100 * Math.Sign(res));
}

please note that your algorithm doesn't apply to your given examples.

Upvotes: 0

kriss
kriss

Reputation: 24177

I strongly suspect that your sample function is broken. Is it a copy paste or did you retyped it ?

decimal CalculateSides(decimal side, decimal vig)
{
    decimal newSide = side - vig;
    newSide = -(newSide < 0) ? newSide + 100 : newSide - 100;
    return (newSide < 0) ? newSide + 100 : newSide - 100;
}

Just try with CalculatesSides(115, 20) you get -95, unlikely to be what you want. (I I understand well result should be -105).

However what you where trying to write seems clear enough. I believe it should be:

decimal CalculateSides(decimal side, decimal vig)
{
    decimal newSide;
    side = (side < 0) ? side + 100 : side - 100;
    newSide = side - vig;
    return (newSide < 0) ? newSide - 100 : newSide + 100;
}

This is quite straightforward and won't be easy to optimize

  1. change mode from 100base to 0base
  2. compute in zero base
  3. convert result base from 0base to 100base

You can do some tricks based on signs to avoid the tests as other suggested, but the result will be quite obfuscated and probably slower.

My advice would be to leave it that way.

Upvotes: 2

starblue
starblue

Reputation: 56772

One sensible way to handle this would be to compute internally with ordinary numbers which go from positive to negative at zero, and only add/subtract 100 for presentation.

Upvotes: 6

paxdiablo
paxdiablo

Reputation: 881423

Optimization is generally done to make something run faster. Have you actually found that your code is not running fast enough? I suspect not.

If your code generates the right results and does it in such a way that it doesn't take a great deal of time, leave it alone, and concentrate on other code that's an actual rather than a perceived, problem.

If you're just worried about the way it looks, add some comments to explain how it works. You would most likely have to do that anyway with a one-formula solution so you may as well not waste your effort.

Upvotes: 1

Related Questions