32 位整数缩放,无溢出
32bit integer scaling with no overrun
嗨,我有以下值:
uint32_t value = 1230000;
uint32_t max_value = 1234567;
现在,我想执行缩放:
uint32_t scaled = value * 1000000 / max_value;
问题是如果我使用 32 位整数,它会溢出这么大的数字。 另一方面,我不能使用64位。知道如何正确实现提到的缩放吗?
编辑
值得一提的是,我正在研究STM32 - 一个32位微控制器,执行64位乘法和除法非常昂贵。因此,我想避免它们。
您可以通过将比例视为以 1000 为基数的数字来做到这一点:
value = value_high*1000 + value_low
。分别计算 value_high
和 value_low
对缩放的贡献,将中间值存储为分数:scaled = scaled_int + scaled_remainder/max_value
uint32_t value_low = value%1000;
uint32_t value_high = value/1000;
uint32_t scaled_int, scaled_remainder;
uint32_t low = value_low * 1000000;
scaled_int = low / max_value;
scaled_remainder = low % max_value;
scaled_int += value_high * 810; // pre-calculated 1000*1000000 / max_value
scaled_remainder += value_high * 730; // pre-calculated 1000*1000000 % max_value
scaled_int += scaled_remainder / max_value;
scaled_remainder = scaled_remainder % max_value;
此外,您不必使用基数 1000,基数 1024 可能会更快一些。只要第 4 行和第 8 行没有溢出其最大值,它应该可以工作。
你可以像下面这样将scaled
声明为unsigned long long
类型,然后相应地进行显式类型转换。
unsigned long long scaled = (unsigned long long)value * 1000000 / max_value; /* make either operand of unsigned long long type explicitly */
printf("%llun",scaled);
如果你的转换器可以支持64位,那么
uint32_t scaled =(uint32_t)((uint64_t)value * 1000000 / max_value);
如果支持浮动,则
uint32_t scaled =(uint32_t)(value *1.0 / max_value* 1000000);
会有一点精度损失。
最快的缩放方法是使用 2 个功率比例因子。
即使你有两个数字使用不同的比例因子缩放 - 算术是微不足道的。
例:
uint32_t scaledDiv(uint32_t a, uint32_t b, uint32_t *sclef)
{
*sclef = __builtin_clz(a);
a <<= *sclef;
return a/b;
}
问题是形式上的:value/max_1 = x/1000000
.
如果不以封闭形式求解,则可以使用平分迭代计算最接近的x
。
uint32_t step=max_value>>1;
uint32_t v=0, x=0, step2=1000000/2 << 12;
// step2 has been scaled to add extra precision
while(step) {
if (value > v+step) { v+=step; x+=step2; }
step>>=1; step2>>=1;
}
x=(x+2048)>>12; // scale down and round
结果将在 32 次迭代中完成。
相关文章:
- UE4-如何在给定4个屏幕坐标的情况下缩放纹理或材质
- 计算缩放多边形的比例,得到给定的多边形面积
- QwtPlot具有相等的轴和自动缩放
- 如何在directx/c++中进行平移/缩放操作
- 在Qt中实现无限可缩放的画布
- 是否可以为 QPixmap 派生类嵌入缩放方法?
- 形状对象的旋转和缩放不正确C++
- 如何在 OpenSceneGraph 中缩放/旋转/移动资产
- 如何在OpenGL(GLFW,很高兴)中进行2D缩放?
- 改变或缩放两个正态分布以具有特定的相关系数
- SDL2 调整窗口大小后如何缩放鼠标坐标?
- 如何在OpenGL中正确旋转和缩放对象?
- 仅当类型为 std::complex 时,才进行缩放
- 将 VS Code 用于跨平台可缩放C++项目
- 根据帧速率缩放/缩小数字
- 在 c++ 中缩放浮点值
- 如何防止 DirectX C++程序的拉伸/缩放
- 使用提升几何缓冲区缩放多边形时的冗余折点
- 为什么我不能使用 Sphere 来缩放字形?
- 32 位整数缩放,无溢出