在给定值附近获得随机exception

我想在double类型的已知值数组中添加一种纹波。 我指出这一点,因为Random.Next / Random.NextDouble()表现不同。

我如何才能最好地完成这项任务?

假设我在数组中有20个值,
List arr = new List() { 40, 40, 40, 40 ..... };
20个值,在40的平均值,总共800,以使其更容易。

在这个方法之后,我希望整体总数仍然是800,但每个单独的值都应该修改。 值应该是正数,因为它们之后是total+=i

到目前为止,使用给定数量的值的百分比来解决该问题。
1.0 / 20 = 0.05, then multiplicate that with the total and the iteration number. Then subtract the result from the remainder. Finally i just return a sort by new Guid() 1.0 / 20 = 0.05, then multiplicate that with the total and the iteration number. Then subtract the result from the remainder. Finally i just return a sort by new Guid()

正如您已经看到的,这种方法只是有点了不起,而只有大约5-20个值。 就我今天的情况而言,这个数组需要保持500-2000个值(每个值为0.2-0.05%)。

相反,我希望有一个衍生物或类似的,以40的+ -x%作为基础的失真。 或者,甚至可能更好,+ -x%对arrays中的任何单个值)。

[UPDATE]

我将根据对此问题的回复添加更新问题。

  Random rnd = new Random(); List ripple = new List(); int qty = bArray.Count(); double diff = last.Value - first.Value; if (qty == 1) { double linearAvg = (diff / qty) / 2; ripple.Add(linearAvg); } else { double[] rndarr = new double[qty]; for (int i = 0; i < qty; i++) rndarr[i] = rnd.NextDouble(); double rndArrSum = rndarr.Sum(); for (int i = 0; i < qty; i++) rndarr[i] /= rndArrSum; for (int i = 0; i  1) ? 1 : 0; i < qty; i++) valueOverall += ripple[i]; 

已经允许最后生成的值不重叠。 此外,列表仅包含两个值时发生exception。 qty=1可能看起来很神奇,但它指的是对象bArray在真实中的样子。 无论如何,我认为整个想法都很清楚。

一种方法是生成0到1之间的N个随机数(不包括)。 总结一下。 然后将每个数字除以总和。 您现在有一个N个随机数的列表,总和为1.现在,将每个数字乘以您想要的总和,以得到将进入最终数组的数字。

如果您希望您的值为+/-某个百分比,则使用Random.Next生成某个范围内的随机数并将它们相加。 然后除以总数得到总和为1的数字列表。最后一步是相同的。

另一种方法是循环遍历数组并按百分比值扰动。 完成后,计算总数的距离,并在所有数字中平均添加超额金额。 这是一些示例代码:

 var test = Enumerable.Repeat(40, 100).ToArray(); var percent = 0.5d; var rand = new Random(); var expectedTotal = test.Sum(); var currentTotal = 0d; var numCount = test.Count(); for (var i = 0; i < numCount; i++) { var num = test[i]; var range = num * percent * 2; var newNum = num + (rand.NextDouble() - 0.5) * (range); currentTotal += newNum; test[i] = newNum; } var overage = (expectedTotal - currentTotal); for (var i = 0; i < numCount; i++) test[i] += overage / numCount; 

以下是我的解决方案。

基本上,它将每个值“抖动”某个指定的百分比,然后检查原始总数和“抖动”总数之间的差异。 为了使最终总数与原始总数相匹配,它会为每个“抖动”值添加一个固定金额。

从数学的角度来看,我认为这不是一个很好的解决方案,因为我认为在每个值中加入平坦的数量可能会扭曲每个值的实际百分比。 可能有一种更加数学上正确的方法来在整个值集中应用余数,以保持预期的abberation百分比,但我想这样做需要多次传递,而这个解决方案完成了一定数量的经过。

 // prepare data double[] values = new double[20]; for (int i = 0; i < values.Length; i++) { values[i] = 40.0; } // get the original total double originalTotal = 0.0; for (int i = 0; i < values.Length; i++) { originalTotal += values[i]; } // specify an abberation percentage double x = 0.05; // jitter each value +/- the abberation percentage // also capture the total of the jittered values Random rng = new Random(); double intermediateTotal = 0.0; for (int i = 0; i < values.Length; i++) { values[i] += values[i] * (rng.NextDouble() - 0.5) * (2.0 * x); intermediateTotal += values[i]; } // calculate the difference between the original total and the current total double remainder = originalTotal - intermediateTotal; // add a flat amount to each value to make the totals match double offset = remainder / values.Length; for (int i = 0; i < values.Length; i++) { values[i] += offset; } // calculate the final total to verify that it matches the original total double finalTotal = 0.0; for (int i = 0; i < values.Length; i++) { finalTotal += values[i]; } 

为连续数字之间的每一步选择一个随机数(对称为零)。 然后,将其添加到第一个,并从第二个中减去它:

 for(int i=1; i 

这应该确保数组的总和保持相同(模数浮点错误),而数组元素都被修改。