如何按总和为 1 的降序生成浮点数列表?

How to generate list of floats in descending order that sum to 1?

我想生成一个大小为 M 的浮点数列表,其中列表中的每个项目都大于其他进行中的项目,即降序。并且列表的总和必须总和为 1。并且对于相同的 M 量级,我可以生成多个遵守给定约束的列表。

我正在考虑以下形式的等式:

Xi+1 = compute([Xi,Xi-1...X0], M, Random)

但我无法弄清楚此功能的范围。提前谢谢你。

好的,那么让我们从0到10中随机抽取10个数字,然后对它们进行排序。然后计算总和并用每个元素除以这个总和重建一个新列表:

import random

# create a non-normalized ascending list of numbers
lst = sorted(random.uniform(0,10) for _ in range(10))
# compute the sum
temp_sum = sum(lst)
# now divide each member by the sum to normalize the list
lst = [i/temp_sum for i in lst]

print(lst,sum(lst))

一个输出可能是:

[0.0340212528820301, 0.05665995400192079, 0.07733861892990018,
 0.07752841352220373, 0.08556431469182045, 0.11628857362899164,      
0.11706017358757258, 0.12523809404875455, 0.14272942597136748, 
0.16757117873543856] 1.0

由于浮点数不准确,总和可能不完全为 1,但会非常接近。

如果您想要数学上可预测的东西...

def makeDescendingUnitArray(length: int):
    if (not isinstance(length, int)) or (length < 1):
        raise ValueError("Array Length must be an int with a value of at least 1")
    if length == 1:
        return [1]
    else:
        constant = 1
        output = list()
        for x in range(length - 2):
            constant /= 2
            output.append(constant)
        return output + [2*constant/3, constant/3]

for arrayLength in range(1, 10):
    array = makeDescendingUnitArray(arrayLength)
    print(array)

生成以下数组...

[1]
[0.6666666666666666, 0.3333333333333333]
[0.5, 0.3333333333333333, 0.16666666666666666]
[0.5, 0.25, 0.16666666666666666, 0.08333333333333333]
[0.5, 0.25, 0.125, 0.08333333333333333, 0.041666666666666664]
[0.5, 0.25, 0.125, 0.0625, 0.041666666666666664, 0.020833333333333332]
[0.5, 0.25, 0.125, 0.0625, 0.03125, 0.020833333333333332, 0.010416666666666666]
[0.5, 0.25, 0.125, 0.0625, 0.03125, 0.015625, 0.010416666666666666, 0.005208333333333333]
[0.5, 0.25, 0.125, 0.0625, 0.03125, 0.015625, 0.0078125, 0.005208333333333333, 0.0026041666666666665]

如果你想要一个数学上可预测的单线,那么就是这个...... (循环向您展示它的样子)

for length in range(1, 10):
    array = [2*x/(length * (length + 1)) for x in range(length,0,-1)]
    print(sum(array), array)

这会产生以下输出。请注意,这与所有其他算法一样容易受到浮点舍入误差的影响。算法有好有坏,但在某些时候,它们都会有一些错误。

Sum: 1.0 Array: [1.0]
Sum: 1.0 Array: [0.6666666666666666, 0.3333333333333333]
Sum: 0.9999999999999999 Array: [0.5, 0.3333333333333333, 0.16666666666666666]
Sum: 0.9999999999999999 Array: [0.4, 0.3, 0.2, 0.1]
Sum: 1.0 Array: [0.3333333333333333, 0.26666666666666666, 0.2, 0.13333333333333333, 0.06666666666666667]
Sum: 0.9999999999999998 Array: [0.2857142857142857, 0.23809523809523808, 0.19047619047619047, 0.14285714285714285, 0.09523809523809523, 0.047619047619047616]
Sum: 1.0 Array: [0.25, 0.21428571428571427, 0.17857142857142858, 0.14285714285714285, 0.10714285714285714, 0.07142857142857142, 0.03571428571428571]
Sum: 1.0 Array: [0.2222222222222222, 0.19444444444444445, 0.16666666666666666, 0.1388888888888889, 0.1111111111111111, 0.08333333333333333, 0.05555555555555555, 0.027777777777777776]
Sum: 0.9999999999999999 Array: [0.2, 0.17777777777777778, 0.15555555555555556, 0.13333333333333333, 0.1111111111111111, 0.08888888888888889, 0.06666666666666667, 0.044444444444444446, 0.022222222222222223]