简体   繁体   English

数量成倍增加,达到最大值

[英]Exponentially increasing number towards maximum

I'm trying to build a retry mechanism for sending e-mails. 我正在尝试建立一种重试机制来发送电子邮件。 I'd like it to be configurable so that administrators can specify both; 我希望它是可配置的,以便管理员可以同时指定两者。

  • The number of retries (intervals) 重试次数(间隔)
  • The maximum number of seconds before giving up 放弃前的最大秒数

A further requirement is that the number of seconds to wait between each retry increases exponentially (or follows some other geometric sequence) up to the maximum. 另一个要求是每次重试之间要等待的秒数成倍增加(或遵循某些其他几何顺序),直到最大值。

Another way of describing the problem is: How can the maximum number of seconds be divided up into X number of intervals where each interval is exponentially larger than its predecessor? 描述问题的另一种方式是: 如何将最大秒数划分为X个间隔,其中每个间隔都比前一个间隔成倍增长?

I'm not sure if this can be expressed using a purely mathematical representation, if not examples in C# would be welcomed. 我不确定是否可以使用纯数学表示形式来表示,否则就不会欢迎使用C#中的示例。 However, I'm really just looking for the logic here so provided the it's well explained I'm sure any language could be easily translated. 但是,我实际上只是在这里寻找逻辑,因此,只要它有充分的解释,我相信任何语言都可以轻松翻译。

Some math : Lets have variable T (total time), N (number of retries), t (time of first try) and e (exponent). 一些数学运算:让变量T (总时间), N (重试次数), t (首次尝试时间)和e (指数)可变。 Each try would take: t*1 , t*e , t*e*e , t*e*e*e , etc.. 每次尝试都将采用: t*1t*et*e*et*e*e*e等。

So total time can be written as T = t*e^0 + t*e^1 + t*e^2 +.. + t*e^N rewritten : T = t*(e^0+e^1+e^2 .. + e^N) . 因此总时间可以写成T = t*e^0 + t*e^1 + t*e^2 +.. + t*e^N重写: T = t*(e^0+e^1+e^2 .. + e^N) We can calculate the sum of powers as : sum = (e^N-1)/(e-1) . 我们可以将总和计算为: sum = (e^N-1)/(e-1)

So given T , N and e , we can calculate t as : t = T/((e^N-1)/(e-1)) 因此给定TNe ,我们可以将t计算为: t = T/((e^N-1)/(e-1))

To calculate time for i th iteration use : ti = t*e^i 要计算第i次迭代的时间,请使用: ti = t*e^i

For example, given T = 124(s), N = 5(tries) and e = 2, the first interval will be 124/((2^5-1)/(2-1)) = 4s . 例如,给定T = 124(s),N = 5(tries),e = 2,则第一个间隔将是124/((2^5-1)/(2-1)) = 4s The following intervals will then be : 以下间隔将是:

  • 0th interval: 4s (t*e^0) 第0间隔:4秒(t * e ^ 0)
  • 1st interval: 4*2 = 8s (t*e^1) 第一个间隔:4 * 2 = 8s(t * e ^ 1)
  • 2nd interval: 8*2 = 4*2*2 = 16s (t*e^2) 第二间隔:8 * 2 = 4 * 2 * 2 = 16s(t * e ^ 2)
  • 3rd interval: 16*2 = 4*2*2*2 = 32s (t*e^3) 第三间隔:16 * 2 = 4 * 2 * 2 * 2 = 32s(t * e ^ 3)
  • 4nd interval: 32*2 = 4*2*2*2*2 = 64s (t*e^4) 第四间隔:32 * 2 = 4 * 2 * 2 * 2 * 2 = 64s(t * e ^ 4)

For total time of 124s of waiting. 总等待时间为124秒。

Sorry for the formatting. 抱歉,格式化。 This question would probably be better for Mathematics . 这个问题对数学可能会更好。

The code to calculate all intervals would be : 计算所有间隔的代码为:

public static void TestFunction(int max, int numIntervals) {

    List<double> intervals = new List<double>();

    double exponent = 2;

    double n = Math.Pow(exponent, numIntervals) - 1;
    double d = exponent - 1;

    double t = max / (n / d);

    for (int x = 0; x < numIntervals; x++) {
        double interval = t * Math.Pow(exponent, x);
        intervals.Add(interval);
    }

}

I am not sure how useful this answer is but it was certainly fun to create. 我不确定这个答案有多有用,但是创建它肯定很有趣。 What makes this answer somewhat different is that it computes the base used for the exponential computation of the time intervals. 使这个答案有些不同的是,它计算了用于时间间隔指数计算的基数。

So the input is a total time as well as a number of intervals to divide this time span into. 因此,输入是一个总时间以及将该时间跨度划分为多个时间间隔。 The length of the first interval is specified and the challenge is to compute the remaining intervals to ensure that they increase exponentially and sum to the total time. 指定了第一个间隔的长度,挑战是计算剩余间隔,以确保剩余间隔成指数增长并求和为总时间。

This can be formulated as a mathematical equation: 可以用数学公式表示:

t∙x 0 + t∙x 1 + ... + t∙x n = T t∙x 0 + t∙x 1 + ... + t∙x n = T

t is the length of the first interval and T is the total time. t是第一个间隔的长度, T是总时间。 n is the number of intervals and x is the unknown base. n是间隔数, x是未知基数。

Assuming that x is not 1 then this equation can be rewritten into a standard form for a polynomial equation: 假设x不为1,则可以将该方程重写为多项式方程的标准形式:

x n - r∙x + r - 1 = 0 x n - r∙x + r -1 = 0

where r = T/t is the ratio between the total time and the length of the first interval. 其中r = T / t是总时间与第一个间隔的长度之间的比率。

As far as I know this equation has no general solution but it can be solved using an algorithm in a numerical analysis library. 据我所知,该方程式没有通用解,但可以使用数值分析库中的算法求解。 I chose a Newton-Raphson algorithm from the Math.Net Numerics library available on NuGet . 我从NuGet上可用的Math.Net Numerics库中选择了Newton-Raphson算法。 For this algorithm the first derivative of the polynomium is required and this is 对于此算法,需要多项式的一阶导数,这是

n∙x n - 1 - r n∙x n -1 - r

Putting it all together to create a sequence of exponentially growing time spans to wait: 将所有这些放在一起以创建一系列等待时间成倍增长的时间跨度:

IEnumerable<TimeSpan> ExponentialTimeSpans(TimeSpan firstTimeSpan, TimeSpan totalTimeSpan, Int32 count) {
  var ratio = totalTimeSpan.TotalSeconds/firstTimeSpan.TotalSeconds;
  var @base = RobustNewtonRaphson.FindRoot(
    x => Math.Pow(x, count) - ratio*x + ratio - 1,
    x => count*Math.Pow(x, count - 1) - ratio,
    1d + 1E-8, // Assume that base is > 1
    100d // Arbitrary (but BIG) upper limit on base
  );
  for (var i = 0; i < count; i += 1)
    yield return TimeSpan.FromSeconds(firstTimeSpan.TotalSeconds*Math.Pow(@base, i));
}

Note that you easily can provide input with no solutions and that will result in an exception being thrown. 请注意,您可以轻松地提供没有解决方案的输入,这将导致引发异常。 However, any sensible input based on the original problem statement should work as expected. 但是,任何基于原始问题陈述的明智输入均应按预期工作。

Something like the following maybe? 像下面这样的东西?

var time_in_seconds = 10000; // usually done in milliseconds, so lets say 10 sec.

// if email fails:
time_in_seconds *= 10; 
// So, next will be 100, 1000, etc. & you get your exponential increment.

Step one - a simple solution - work in reverse! 第一步-一个简单的解决方案-反向进行! (Where the reduction is 50%) (减少幅度为50%)

I need to fit 10 intervals into 128 seconds. 我需要在128秒内调整10个间隔。

Interval :  Time (Of occurrence)
1        :  128
2        :  64
3        :  32
4        :  16
5        :  8
6        :  4
7        :  2
8        :  1
9        :  1/2
10       :  1/4

Note: The above works fine (to keep under X, just start with X/2). 注意:上面的方法工作正常(要保持在X下,只需从X / 2开始)。 The below, not so much. 下面,不是很多。 This techniques can be applies iteratively to find a 'good' solution though for now. 尽管目前,可以迭代地应用此技术以找到“好的”解决方案。

Great, but what happens if we need a minimum? 很好,但是如果我们需要最低限度的价格怎么办? 1/128th of a second between retries at the start may be unnecessary. 重新开始之间的两次重试之间不需要1/128秒。 So what we need to do, is vary the exponential. 因此,我们需要做的是改变指数。

Now the above can be written as result = 1/4 * 2^9 or more generally result = startingInterval * 2^(n-1) . 现在,上面的代码可以写成result = 1/4 * 2^9或更一般地, result = startingInterval * 2^(n-1) However we know the result we want, so we need to rearrange this formula. 但是,我们知道想要的结果,因此我们需要重新排列此公式。

(result/startingInterval)^(1/(n-1)) = base

With the above values: (128/(1/4))^(1/(10-1)) = base = 2 具有以上值: (128/(1/4))^(1/(10-1)) = base = 2

Or in other words, to get a total time of 128s starting with an interval of 1/4s and using 10 attempts (including the first one) then we need to increase the length between intervals by a factor of 2 each attempt. 换句话说,要使总时间为128秒,以1 / 4s的间隔开始并使用10次尝试(包括第一次尝试),则我们需要将间隔之间的长度每次尝试增加2倍。

Declare a max threshold value as well an offset to be added for each retry. 声明最大阈值以及每次重试要添加的偏移量。

int maxRetryCount = 5;
int offSet = 10000;
int currRetryCount = 0;
int waitTime = 1000; //default value

while(currRetryCount < maxRetryCount)
{
    try
    {
        //Send Email 
        // break out once the email is send
        break;
    }
    catch
    {
        //Wait for a while
        Thread.Sleep(waitTime);

        //increase the wait time for next time
        waitTime += offSet;
        currRetryCount++;
    }
}

Here the code will attempt for at most 5 times to send an email where the wait time will increase by 10 sec each time. 在这里,代码最多尝试5次发送电子邮件,每次等待时间将增加10秒。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM