You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C++二维std::vector存储uint8_t网格赋值后部分位置取值异常问题

问题根因
  • 浮点数精度丢失是核心问题。0.05属于十进制有限小数,但对应二进制是无限循环小数,无法被浮点类型精确存储。你在嵌套循环中每次累加grid_resolution(0.05)的操作,累计多次后会产生明显的精度误差,要么实际值略小于理论值,要么略大于理论值,直接导致两类异常:
    1. 循环终止条件判断错误,部分本应执行的循环分支被跳过,对应预期网格位置从来没有被赋值为255
    2. 计算m_co、n_co时,带误差的浮点值除以0.05后得到的结果略小于理论整数,强制转int时会被截断为更小的索引值,导致赋值到了错误的网格位置,预期位置没有被修改
  • 你在循环内部打印的m_co、n_co本身就是精度误差带来的错误索引,你给错误的索引位置赋值为255,打印自然显示255;但循环结束后你访问的是预期的正确索引位置,这些位置从未被赋值,所以值为0。
  • 坐标转网格索引的逻辑不严谨,直接强制转换int没有做四舍五入,同时没有做边界校验,极端情况下可能出现数组越界访问的未定义行为。
  • rows、cols使用浮点类型定义,传入vector构造函数时隐式转int,如果因精度问题导致10/0.05计算结果为199.9999999而非200,会直接导致网格实际大小小于预期,后续访问高索引位置属于越界操作,值是未定义的。
修复方案

完全避免浮点循环累加操作,改由整数计算网格索引范围后再遍历,从根源上消除精度问题:

  1. 先将所有浮点坐标转换为整数网格索引,转换时做四舍五入处理
  2. 直接计算需要赋值的索引上下界,整数遍历赋值
  3. 增加边界校验,避免越界访问

修复后代码如下:

#include <iostream>
#include <vector>
#include <cmath>
using namespace std;

int main()
{
    const float grid_width = 10.0f;
    const float grid_height = 10.0f;
    const float grid_resolution = 0.05f;
    // 计算行列数时先四舍五入再转int,避免精度导致大小错误
    const int rows = static_cast<int>(round(grid_width / grid_resolution));
    const int cols = static_cast<int>(round(grid_height / grid_resolution));

    vector<vector<float>> landmarks = {{2,2},{8,8},{2,8},{8,2},{3,2},{3.5,2.1},{4.0,3.5},{4.5,2.0},{5.0,3.0}};
    vector<vector<uint8_t>> grid(rows, vector<uint8_t>(cols, 0));

    // 周边3x3对应偏移量为1,如果需要0.1米范围(2个网格单位)可改为2
    const int OFFSET = 1; 
    for(const auto& pt : landmarks)
    {
        // 坐标转索引时四舍五入,避免截断误差
        int x_co = static_cast<int>(round(pt[0] / grid_resolution));
        int y_co = static_cast<int>(round(pt[1] / grid_resolution));
        
        // 计算索引范围,同时做边界裁剪避免越界
        int x_start = max(0, x_co - OFFSET);
        int x_end = min(rows - 1, x_co + OFFSET);
        int y_start = max(0, y_co - OFFSET);
        int y_end = min(cols - 1, y_co + OFFSET);
        
        // 整数遍历赋值,完全消除浮点精度问题
        for(int x = x_start; x <= x_end; x++)
        {
            for(int y = y_start; y <= y_end; y++)
            {
                grid[x][y] = 255;
            }
        }
    }

    // 测试输出
    cout << unsigned(grid[18][18]) << endl;
    cout << unsigned(grid[18][22]) << endl;
    cout << unsigned(grid[22][22]) << endl;
    cout << unsigned(grid[22][18]) << endl;
    cout << unsigned(grid[17][17]) << endl;
    cout << unsigned(grid[20][18]) << endl;
    return 0;
}

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.06 10:57:01