C++“Map”数字范围

58wvjzkj  于 2023-03-01  发布在  其他
关注(0)|答案(4)|浏览(186)

在C或C++中,或者只是一般的数学方法中,有没有更好的方法来Map数字的比率,同时保留或舍入数据?
以下面的例子为例

double cdp = 17000.0;    
float integ = 30000.0 / 255;
int val = cdp / integ;

color = color + RGB(val, val, val);

这里我想将一个数字范围[0,30000]Map到一个值[0,255]

iecba09b

iecba09b1#

如果我没理解错的话,你可以用一个简单的线性插值来实现,它的工作原理是:

x = (inValue - minInRange) / (maxInRange - minInRange);
result = minOutRange + (maxOutRange - minOutRange) * x

其中,在您的示例中,inValue是30,000之外的数字。最小输入范围= 0,最大输入范围= 30,000,最小输出范围= 0,最大输出范围= 255。

jobtbby3

jobtbby32#

乘以255,然后除以30000。使用整数格式,该格式可以保存两个范围限制(30000*255或765万)的乘积。这样可以避免中间浮点值的精度问题。

6rvt4ljy

6rvt4ljy3#

如果要舍入到最接近的值,而不是截断任何小数部分,则必须执行以下操作:

double prod = cpd * 255; //double is big enough to hold the product without loss of precision
val = (int)(prod / 30000 + 0.5); //Adding 0.5 turns truncation into rounding.
fnvucqvd

fnvucqvd4#

如果有人需要模板版本的@user1118321建议

template<typename T>
    struct interpolation{
      T min_in, max_in, min_out, max_out;
      interpolation(T min_in_, T max_in_, T min_out_, T max_out_): min_in(min_in_), max_in(max_in_), min_out(min_out_), max_out(max_out_){
      }
    };

    template<typename T, typename interpolate_type>
    T map_range_1d(T value, interpolate_type interp_type){
        double x = (value - interp_type.min_in) / (interp_type.max_in - interp_type.min_in);
        return interp_type.min_out + (interp_type.max_out - interp_type.min_out) * x;    
    }

    template<typename T, typename interpolate_type>
    std::pair<T,T> map_range_2d(T value_x, T value_y, interpolate_type interp_type_x, interpolate_type interp_type_y){
        std::pair<T,T> mapped_values = {map_range_1d(value_x, interp_type_x), map_range_1d(value_y, interp_type_y)}; 
        return mapped_values; 
    }

    typedef interpolation<double> interp1d;
    constexpr auto map_range2d = &map_range_2d<double, interp1d>;
    constexpr auto map_range1d = &map_range_1d<double, interp1d>;

如何使用它

interp1d x_range(min_x_in, max_x_in, min_x_out, max_x_out);
        double index_local = map_range1d(456, x_range);

相关问题