12

I guess this is a math question and not a programming question, but what is a good way to create a formula that has diminishing returns?

Here are some example points on how I want the curve to look like.

f(1) = 1
f(1.5)= .98
f(2) = .95
f(2.5) = .9
f(3) = .8
f(4) = .7
f(5) = .6
f(10) = .5
f(20) = .25 

Notice that as the input gets higher, the percentage decreases rapidly. Is there any way to model a function that has a very smooth and accurate curve that says this?

Another way to say it is by using a real example. You know in Diablo II they have Magic Find? There are diminishing returns for magic find. If you get 100%, the real magic find is still 100%. But the more get, your actual magic find goes down. So much that say if you had 1200, your real magic find is probably 450%. So they have a function like:

actualMagicFind(magicFind) = // some way to reduced magic find
egervari
  • 22,372
  • 32
  • 121
  • 175

4 Answers4

17

f(x) = f(0)e-rx


Where r is the rate of compounded diminishing return

This is just exponential decay

Community
  • 1
  • 1
Pierreten
  • 9,917
  • 6
  • 37
  • 45
  • Two questions, what is e? and is that e to the power of -r? – egervari May 11 '10 at 19:05
  • e is Euler's number; and everything after the ^ is exponetiated – Pierreten May 11 '10 at 19:07
  • 3
    -rx (superscript tag) – Robert Harvey May 11 '10 at 19:11
  • I'm not sure how to translate this. Let's take the magic find example I said above. Here are some examples: realMF(0) = 0, realMf(100)=100, realMf(200)=180, realMf(300)=250, realMf(600)=350, realMf(1200)=450. In this case, what is x? I looked on wikipedia and it's time, but I don't know the target time. – egervari May 11 '10 at 19:15
  • @egervari: if you want a curve "flat" around zero, use the Gaussian curve f(x)~e^(-x²/a²). f(x)~xe^(-rx) will produce behavior like in your comment, try realMF(x)=100x*e^(-x/1000) – Anton Tykhyy May 11 '10 at 19:18
  • @egervari: If you want a math equation that satisfies those points, you need to employ [curve fitting.](http://en.wikipedia.org/wiki/Curve_fitting) – Robert Harvey May 11 '10 at 19:18
  • 1
    x is just the independent variable; it can be time, distance, accumulated magic etc. Based on the points on your curve defined in the question; you should be able to find r. You already know that f(0) = 1; so that simplifies the function where you are only dealing with f(x) = e^-kx . The second point plugged in will yield .98 = e^-(k*1.5) . Solve this for k by taking the naturallog of both sides. – Pierreten May 11 '10 at 19:25
  • Thanks for all the advice. I eventually got to what I wanted with a combination of all the help here. LOL. I had many formulas in a game that are similar, so I would imagine each one is going to be different. One of the formulas went like this, where ratio was x in the my first examples: math.pow(math.E, -ratio / 20) * speed – egervari May 11 '10 at 20:11
  • Your `math.pow(math.E, stuff)` can be replaced by `math.exp(stuff)` in Java. See http://java.sun.com/j2se/1.5.0/docs/api/java/lang/Math.html#exp(double) – dreeves May 12 '10 at 19:40
7

f(1) = 1
f(1.5)= .98
f(2) = .95
f(2.5) = .9
f(3) = .8
f(4) = .7
f(5) = .6
f(10) = .5
f(20) = .25

This doesn't make sense: for 3-5, adding one each time subtracts .1. With a real curve the output wouldn't be evenly spaced between any evenly spaced inputs. In other words, your curve is not a curve, as you can see by the graph: https://docs.google.com/spreadsheets/d/1EEbRxTyYalPSyQ93rcIbKiIvmYRX1lhRvkRh_HyofJc/edit?usp=sharing

So let's just ignore your "curve"; There are several ways to create diminishing returns. One of my favorites is:

f(x) = (x*a) / (x+b) + c

You can make a, b, and c anything you want. With this format a + c essentially* becomes your maximum possible output, c is your minimum, and b controls how quickly the output values scale and its effectiveness is relative to the value of a. This curve, of course increases the output as the input increases, whereas your example wants to decrease the output as the input increases. To fix this, you can swap the numerator and denominator:

f(x) = (x+b) / (x*a) + c

This makes the minimum output value equal to 1/a + c, the maximum output value approaches infinity as the input value approaches 0. b once again controls how quickly the output scales and its effectiveness is relative to the value of a.


Another approach would be to use something like what was mentioned by @Pierreten, though I'm not sure why he explicitly uses e:

a^(-bx)

Both a and b have a profound impact on how quickly the curve scales. If a is greater than 0 and less than 1, the output will increase as the input increases, but will also have the opposite effect, meaning it will have increasing returns, not diminishing. If a is greater than 1, then you'll see the desired effect of the output decreasing as the input increases with diminishing returns. The following is the closest thing I found to the numbers you described:

f(x) = 1.01^(-6.96607x)
f(0) = 1
f(1) = 0.933
f(3) = 0.812
f(10) = 0.5
f(20) = 0.25

There are several other options as well, but this is long enough.

Joe Zim
  • 1,787
  • 1
  • 15
  • 16
3

Any inverse exponential function, such as f(x) = 1/(x2). Modify the exponent to adjust the steepness of the curve.

Barry Brown
  • 20,233
  • 15
  • 69
  • 105
0

This is the best I have been able to turn this into excel, any help improving this is appreciated, it works I just cannot get it to work like I expect it.

Formula in M column is:

Output increases as input increases

=((I6*J6)/(I6+K6))+L6

Output decreases as input increases

=((I12+K12)/(I12*J12))+L12

Image of Excel Table

The idea behind this is to calculate a diminishing return for the more volume of product a customer purchases, the lower the amount of discount he gets, while he still gets some, its a lot less

Full thread of the excel quest to get this formula working here (for those interested)

Here

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
  • 1
    This again seems an attempt to get help with your problem, instead of an attempt to answerr the question at the top of the page. If I am mistaken, please make the answering aspect according to [answer] more obvious. Or just remove anything that is not answering the question here. (You can put it into a comment if you like.) – Yunnosch Jul 11 '22 at 06:42