You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

从数组选取15个随机数求和至47826.53失败,变量k未递增求排查

问题分析与修复方案

咱们先拆解下你的代码里导致k不递增、程序运行失败的几个核心问题:

1. 数组索引越界的致命问题

  • 你的x数组有23个元素,合法索引是0~22,但用rand() % 24生成的RandIndex会是0~23,这会直接超出数组范围,访问x[23]v[23]会触发未定义行为——可能导致程序崩溃,也可能乱改其他变量的值,比如影响k的递增逻辑。
  • 另外,v数组定义成int v[22],但需要标记23个元素的选中状态,长度必须改成23,不然访问v[22]同样越界。

2. 错误的元素跳过逻辑

你加了RandIndex != 0的判断,这会直接跳过x[0]这个元素。如果随机到索引0,代码就不会执行s += x[RandIndex]k++,自然会出现k一直不递增的情况。如果你的需求是允许选中第一个元素,直接去掉这个判断;如果确实要跳过,得先确认剩下的22个元素里能选出15个总和符合要求的数。

3. 浮点数直接比较的精度陷阱

浮点数在存储和计算时存在精度误差,用s != 47826.53作为循环终止条件几乎永远不会成立——哪怕实际总和是目标值,s的实际值可能是47826.52999999999或者47826.53000000001,导致循环无限运行。正确的做法是判断差值的绝对值是否小于一个极小的阈值,比如abs(s - 47826.53) < 1e-6

4. 重置逻辑遗漏总和清零

k > 15或者s > 47826.53时,你重置了v数组和k,但没把s重置为0。这会导致下一轮循环时s还是之前的超大值,一直满足s > 47826.53,进入无限重置的死循环,k自然一直是0。


修复后的代码

#include <iostream>
#include <stdlib.h>
#include <time.h>
#include <cmath> // 用于处理浮点数的绝对值
using namespace std;

int main () {
    float x[23] = { 6653.05, 1939.89, 6649.05, 2755.74, 5270.62, 6216.57, 4812.92, 7919.50, 4807.46, 1698.00, 849.01, 1415.01, 1698.00, 4811.61, 1698.21, 7355.99, 4817.37, 566.75, 2266.47, 1699.86, 3966.33, 849.93, 849.93 };
    int v[23] = { 0 }; // 改为23个元素,对应x的所有索引
    float s = 0;
    int k = 0;
    int RandIndex = 0;

    srand(time(0)); // 初始化随机数种子,避免每次运行随机结果重复

    while (fabs(s - 47826.53) > 1e-6) { // 用精度阈值判断是否达到目标
        RandIndex = rand() % 23; // 生成0~22的合法索引
        if (v[RandIndex] == 0) { // 若需要跳过x[0],可加回RandIndex !=0的判断
            s += x[RandIndex];
            k++;
            v[RandIndex] = 1;
            cout << "当前总和: " << s << endl;
        }

        // 选中数量超标或总和超出目标时,重置所有状态
        if (k > 15 || s > 47826.53 + 1e-6) { // 加阈值避免精度问题导致误判
            for (int i = 0; i < 23; i++) v[i] = 0;
            k = 0;
            s = 0; // 必须重置总和
            cout << "重置状态,重新开始选择..." << endl;
        }
    }

    cout << "\n最终总和: " << s << endl;
    cout << "选中的数:" << endl;
    for (int i = 0; i < 23; i++) {
        if (v[i] != 0) {
            cout << "Number " << i+1 << ": " << x[i] << endl;
        }
    }
    return 0;
}

额外优化提示

  • 随机数种子:原代码没加srand(time(0)),每次运行的随机序列都是固定的,加上它能让每次运行的随机结果不同。
  • 效率问题:这种随机尝试的方法运气不好时会运行很久,如果需要更高效的方案,可以考虑用回溯算法枚举所有15个元素的组合,直接找到符合总和要求的集合。

内容的提问来源于stack exchange,提问作者Reef1

火山引擎 最新活动