我正在寻找生成一些随机数字,这些数字可以累加为一个特定数字。
示例:
范围(10,35)
总和:100
要生成的数字:5
最好的方法是什么?试图写我自己的逻辑,但作为一个伪代码看起来很混乱。我可以遵循的任何算法?看到类似的问题,但没有得到适当的答案。
答案 0 :(得分:1)
一个想法可能是考虑以下事实:前4个数字的随机性将有助于最后一个数字的随机性。遵循您的示例:
您现在有5个随机数,总计为100。
注意:@derHugo的话非常好。增量调整可双向进行。如果第一个数字是10,则下一个数字将是rand(10 + 10,35)= rand(20,35)。等等
答案 1 :(得分:0)
您只需使用System.Random
来生成范围之间的随机数,然后在检查总和是否等于结果时继续将它们相加。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class RandomNumberGenerationWithSum : MonoBehaviour
{
string output = "";
int sum = 0;
int result = 100; //Give the sum
void Start()
{
System.Random r = new System.Random();
while (sum != result)
{
int add;
if ((result - sum) > 35) //maximum limit
{
add = r.Next(10, 35); //define the range
}
else
{
add = r.Next(result - sum + 1);
}
sum += add;
output += add.ToString() + " + ";
}
output = output.Remove(output.Length - 2);
Debug.Log("Output: " + output);
}
}
答案 2 :(得分:0)
在这里,我更新了一个使用数组创建的新脚本。因此,您可以在总体中增加大小,例如5。因此,将仅生成5个随机数以将值相加以获得结果。希望这会有所帮助!
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class RandomInitial : MonoBehaviour
{
public int[] population;
int result = 100; //Give the sum
int z;
private bool Check = true;
void Start()
{
}
void Update()
{
if (Check == true)
{
for (int i = 0; i < population.Length; i++)
{
population[i] = Random.Range(10, 35);
}
for (int i = 0; i < population.Length; i++)
{
z += population[i];
}
Debug.Log("value " + z);
}
if (z == result)
{
Debug.Log("Success");
Check = false;
}
else
if (z != result)
{
z = 0;
}
}
}
答案 3 :(得分:0)
好吧。所以最简单的方法是: 只要做一个循环,从目标数中减去随机数即可。 重复执行n-1次,然后检查剩下的那一个是否在范围内。 我将用php编写代码,而不是将其发布在这里
编辑:在这里
注意:它确实有效,但是它不是没有错误,您必须添加一些防御性的东西,因此它不会超过$ targetNum
<?php
$targetNum = 100;
$randMin =10;
$randMax = 35;
$generateNum = 5;
$numArray = array();
$numLeft=$targetNum;
for($i = 0; $i<$generateNum-1;$i++){
$numArray[$i] = rand($randMin,$randMax);
$numLeft -= $numArray[$i];
if($i==$generateNum-2){
$numArray[$i+1] = $numLeft;
}
}
for($i = 0; $i<$generateNum;$i++){
echo $numArray[$i];
echo ", ";
}
?>
答案 4 :(得分:0)
我遵循Zedka29的回答编写了此JavaScript代码,但是在选择不同数量的数字来生成时遇到了一些错误。在您的示例中,如果最大范围是20,则最终会留下一个缺口,因为在这种情况下,第一个数字可能会小于20。
function genRand(min, max, target, numItems) {
let total = 0;
let maxNum = Math.floor(target/min);
let minNum = Math.ceil(target/max);
if (!numItems) numItems = Math.floor(Math.random() * (maxNum - minNum) + minNum);
let avg = Math.round(target / numItems);
let tries = 0;
while (total < target && tries < maxNum) {
let tmp = Math.floor(Math.random() * (max - min) + min);
if (total + tmp > target) {
tmp = target - total;
}
else if (total + tmp > target - min) {
tmp += target - (total + tmp);
if (tmp > max) {
// SOMETHING WRONG
}
}
else {
if (tmp < avg) {
min += (avg - tmp);
}
else if (tmp > avg) {
max -= (tmp - avg);
}
}
total += tmp;
console.log(tmp + ', new min: ' + min + ', new max: ' + max);
console.log('total: ' + total);
++tries;
}
console.log('numItems ' + numItems);
console.log('nums generated: ' + tries);
}
genRand(10,20,100, 5);
但是,在本文中运行了几次之后,我意识到最后一个数字似乎总是30。10,最小值,大于最大值...我想知道该信息是否有用。
在努力弄清Zedka29的答案出了什么问题之后,我使用递归和数组为这个问题开发了一种蛮力的解决方案。下面的代码将生成范围内所有可能的,唯一的,经过排序的数字组合,这些数字加起来即为总数。要实际生成所需的随机数,请对当前的数字数组进行排序,并检查其是否在此处所述的蛮力方法生成的数组中。注意:此方法使用了不必要的内存,仍然可以对其进行优化,但是无论用户输入了什么,都会避免剩余数太大或太小。
以下是指向repl.it的链接:https://repl.it/@geraldgehrke/RandomLengthsTesting-1
(function(){
const total = 41;
const size = 5;
let arr = [];
let cntrs = new Array(size);
const min = 5;
const max = 10;
let maxNum = Math.floor(total/min);
let minNum = Math.ceil(total/max);
if (minNum > maxNum) {
minNum = maxNum;
}
for (let i = minNum; i <= maxNum; ++i) {
cntrs = new Array(i);
arr = [];
generateSums(total, i, arr, cntrs, min, max);
}
function generateSums(total, size, arr, cntrs, min, max) {
function count(index) {
++cntrs[index];
let sum = 0;
for (let i of cntrs) {
sum += i;
}
if (sum == total) {
arr.push(cntrs.slice(0));
}
if (index < size - 1) {
count(index + 1);
}
}
function loop(prevIndex, loopLevel, maxLoopLevel) {
if (loopLevel < maxLoopLevel) {
for (let i = prevIndex; i < size; ++i) {
loop(i, loopLevel + 1, maxLoopLevel);
}
}
else {
for (let i = prevIndex; i < size; ++i) {
cntrs.fill(min, i+1);
count(i);
}
}
}
cntrs.fill(min, 0);
let sum = 0;
for (let i of cntrs) {
sum += i;
}
if (sum == total) {
arr.push(cntrs.slice(0));
}
count(0);
for (let i = 1; i < max-min; ++i) {
loop(0,1,i);
}
console.log(arr);
}
})();