(已解决) 随机生成 n 个指定范围内的数使其和为目标值

大佬们,我想求助一个关于随机数的写 (算) 法问题,随机生成 n 个指定范围内的数使其和为目标值。

平时工作中会碰到一些凑数的问题,比如开发票时,希望能挑出若干个数使其和等于或者接近于某个值,又或者根据一个总数拆分成某个区间内的 n 个数,各种折腾。

关于第一种组合凑数,之前也求助过类似的问题: 排列组合两种递归写法的效率比较

主要是想求助一下第二种总数随机拆分的情景,我自己折腾了几种不靠谱的写法:

1、随机生成 n 个非负整数使其和为某个值,比如随机生成 3 个整数使其和为 723

=Cnt=3,Sum=723,((Cnt-1).(rand(Sum)).sort()|Sum).((~-~[-1]))

imagepng

这种写法比较简单,缺点是数值的随机分布不均匀,有时候小的很小,大的很大,也不能指定数字生成的范围。

2、于是有了第 2 种写法,用 iterate 迭代无数次,当满足条件时跳出迭代。比如以下写法,随机生成 5 个在区间 [10,20] 内的不重复的整数,使其和等于 72。这种写法就比较傻了,虽然不烧人脑,但烧电脑,出结果的速度完全靠运气,运气不好时,迭代次数跑完也没有正确结果出来,如果设定一个 infinite 的次数,那电脑会跑崩溃。

=spl("=Min=10,Max=20,Cnt=5,Sum=72	/round(rand()*(Max-Min),2),rand(Max-Min+1)
=9e7.iterate(Cnt.(Min+rand(Max-Min)),,~~.sum()==Sum&&(~~.icount()==Cnt))")

imagepng

3、第 3 种写法是先生成 n-1 个指定区间的随机数,然后用目标值去减去这 n-1 个随机数的和,得到的差作为最后一个数,但这个数要根据大小看是否落在指定区间里进行修正。如果数字允许重复那还好,如果要求不重复,我就不道怎么玩下去了。比如以下语句:

imagepng

可复制代码如下:

A B C D
1 >Min=10,Max=1000 / 指定数值范围
2 >N=4,Tgt=2024 / 生成 N 个数,和等于 Tgt
3 =(N-1).(Min+rand(Max-Min+1)) =A3.m(:) / 先生成 N-1 个指定范围内的随机数
4 =Tgt-A3.sum() =A4 / 最后一个数用 Tgt 减去上述 N-1 个数的和得到
5 / 判断最后一个数 A4 是否符合范围,根据大小进行修正。B3、B4 没什么用,只是为了观察初始值
6 for if A4>=Max =d=rand(A4-Max+1)+1 / 随机生成一个数
7 =i=rand(N-1)+1 / 在 N-1 个位置中生成一个随机位置
8 =v=A3(i)+d / 在随机位加上随机数,判断是否合适
9 if between(v,Min:Max) >A3(i)=v
10 >A4-=d
11 else next
12 else if A4<=Min =d=rand(Min-A4+1)+1
13 =i=rand(N-1)+1
14 =v=A3(i)-d
15 if between(v,Min:Max) >A3(i)=v
16 >A4+=d
17 else next
18 else break
19 =A3|A4
20 =A19.sum()==Tgt&&(A19.cand(between(~,Min:Max)))

以上 3 种写法我觉得不咋靠谱:

第一种有点草率,不能指定数字分布的范围,且不能去重;
第二种烧电脑,快慢看运气;
第三种不能随机不重复取值。

这个问题对我来说一直是个困扰,所以,我想恳请大佬们帮忙看看,有闲有心情的时候可否指导一下🙏 🙏 比如,随机数能正态分布 (比较均匀分布在某个区间,不知道表达是否正确),随机数允许重复,随机数不许重复,随机数可以是小数,随机数只能是正整数…等等情况,怎么感觉情况有点大,越说越没边了😄

谢谢🙏 🙏