简体   繁体   English

32位整数缩放,无溢出

[英]32bit integer scaling with no overrun

Hi I have a following values: 嗨,我有以下值:

uint32_t value = 1230000;
uint32_t max_value = 1234567;

Now, I would like to perform scaling: 现在,我想执行缩放:

uint32_t scaled = value * 1000000 / max_value;

The problem is if I use 32bit integer it will overrun for such big numbers. 问题是,如果我使用32位整数,那么对于这么大的数字它将溢出。 On the other hand I cannot use 64bit. 另一方面,我不能使用64位。 Any idea how to properly implement mentioned scaling? 任何想法如何正确实现上述缩放?

EDIT 编辑

Just to mention, I am working on STM32 - a 32-bit micro-controller, where performing 64-bit multiplication and division is extremely costly. 值得一提的是,我正在研究STM32(32位微控制器),在其中执行64位乘法和除法非常昂贵。 Therefore I would like to avoid them. 因此,我想避免它们。

You can do it by seeing scale as a base-1000 number: value = value_high*1000 + value_low . 您可以通过将scale作为一个以1000为底的数字来实现: value = value_high*1000 + value_low Calculate value_high 's and value_low 's contribution to scaled separately, storing the intermediate values as a fraction: scaled = scaled_int + scaled_remainder/max_value 分别计算value_highvalue_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;

Also, you don't have to use base 1000, base 1024 might be a bit faster. 此外,您不必使用以1000为基数,以1024为基数可能会更快一些。 As long as the 4th and 8th line don't overflow at their maximum value, it should work. 只要第4行和第8行不溢出其最大值,它就应该起作用。

you can declare scaled as unsigned long long type like below & then do explicit typecast accordingly. 您可以将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("%llu\n",scaled);

if your translater can support 64bit,then 如果您的翻译器可以支持64位,则

uint32_t scaled =(uint32_t)((uint64_t)value * 1000000 / max_value);

if support float,then 如果支持浮动,则

uint32_t scaled =(uint32_t)(value *1.0 / max_value* 1000000);

There will be a little loss of precision. 会有一点精度损失。

The fastest way of scaling is using the 2 power scale factors. 最快的缩放方法是使用2个功率缩放因子。

Even you have two numbers scaled using different scale factors - the arithmetic is trivial. 即使您有两个使用不同比例因子缩放的数字-该算法也是微不足道的。

example: 例:

uint32_t scaledDiv(uint32_t a, uint32_t b, uint32_t *sclef)
{
    *sclef = __builtin_clz(a);
    a <<= *sclef;
    return a/b;
}

The problem is of form: value/max_1 = x/1000000 . 问题的形式为: value/max_1 = x/1000000

Without solving this in closed form, the closest x can be calculated iteratively using bisection. 无需以封闭形式求解此问题,就可以使用二等分迭代地计算最接近的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

The result will finish in 32 iterations. 结果将在32次迭代中完成。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 从64位整数中提取32位 - extract 32bit from 64bit integer 是否有更有效的方法来获取32位整数的长度(以字节为单位)? - Is there a more efficient way to get the length of a 32bit integer in bytes? 将浮点型32位变量类型转换为无符号整数32位时,会进行哪些位级别更改? - What bit-level-changes are made while typecasting a float 32bit variable to unsigned integer 32bit? C ++:将64位整数与32位整数进行比较是否安全? - C++: Is it safe to compare a 64bit integer with a 32bit integer? 当64位机器上的32位整数溢出时会发生什么? - What happens exactly when a 32bit integer overflows on a 64bit machine? 64位integer类型如何保证32位操作系统上的原子性? - How does 64bit integer type guarantee atomicity on 32bit operation system? 哈希一个32位整数比对3个16位整数进行哈希运算要慢? - hashing a 32bit integer is slower than bitwise operation on hash of 3 16bit integers? 有没有办法让32位C ++编译器遵循16位整数提升规则? - Is there a way to get a 32bit C++ compiler to follow 16bit integer promotion rules? 优化器可以省略从 64 位到 32 位整数类型的分配吗? - Can the optimizer elide assignment from 64bit to 32bit integer types? 尝试从另一个进程读取32位整数时,ReadProcessMemory使应用程序崩溃 - ReadProcessMemory Crashes Application When Trying to Read 32bit Integer From Another Process
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM