热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

尝试仅使用整数数学将0..4096之间的数字乘以0.3

如何解决《尝试仅使用整数数学将0..4096之间的数字乘以0.3》经验,为你挑选了3个好方法。

我试图围绕如何将一个数字从0..4096乘以0.3,只使用带有移位操作和缩放的整数,而不是在C中分割.我是这个东西和任何输入或步骤的新手一步一步的建议会非常有帮助.



1> abligh..:

乘以0.3与乘以相同(0.3*2^n),然后除以2^n.第二阶段相当于右移n.

有价值的是n什么?

要找到这个,请获取最大的整数并找到最大值,n以便在(0.3*2^n)没有溢出的情况下乘以.使用64位无符号整数和4096作为最大值

0.3*2^n <= 2^(64-12)

要么

0.3 <= 2^(64-12-n)

n当RHS等于0.5时,不平等最大

2^-1 = 2^(64-12-n)

所以-1 = 64-12-n,n = 64-12+1 = 53.

所以答案是乘以2^53*0.3然后右移53,即

/* designed to work with input values 0 .. 4096 only */
uint64_t
multiplyby0_3 (uint64_t x)
{
    return (x * 2702159776422297ULL) >> 53;
}

要检查是否没有溢出,我们已经得到了最好的n,来自bc:

2702159776422297*4096 = 11068046444225728512
2^64                  = 18446744073709551616

IE它不会溢出,但如果我们再次乘以2,它就会.

对于32位整数,答案乘以2^21*0.3然后右移21,即

/* designed to work with input values 0 .. 4096 only */
uint32_t
multiplyby0_3 (uint32_t x)
{
    return (x * 629146U) >> 21;
}

最后,通过查看1乘数中的二进制数,可以将任意乘法分解为多个加法.因此,您允许"缩放",我认为这意味着成倍增加.如果不是,这里是32位版本开发的事实,(64位作为练习留给读者版本)62914610011001100110011010(一个整洁的模式,由于重复二进制小数).我们将绕过另一条路并10011001100110011001改为使用.

/* designed to work with input values 0 .. 4096 only */
uint32_t
multiplyby0_3 (uint32_t x)
{
    uint32_t y;
    x += x<<3;    /* * 1001 */
    y = x<<4 + x; /* * 10011001 */
    y += y<<8;    /* * 1001100110011001 */
    y += x<<16;   /* * 10011001100110011001 */
    return y >> 21;
}



2> duskwuff..:

如果你有快速整数乘法,但你没有整数除法,你可以通过乘以1229得到合理的近似值,然后向右移12位.例如:

>> 100 * 1229
122900
>> 122900 >> 12
30

这是有效的,因为1229是关于0.3 * 1 <<12."实际"值为1228.8,因此在某些情况下估计值将高1(4097值中的68个).但它永远不会超过1.


我会在>> 12之前做+2048做一个简单的舍入.
@EOF给定问题中指定的范围的最大中间结果是"1229*4096 = 5033984".这完全在32位整数的范围内; 如果你需要保持16位,那就更难了.

3> chux - Reins..:

使用divu10()下面的经典黑客.我更喜欢*n和shift方法,但我认为我提供了另一个POV.

unsigned mult3tenths(unsigned x) {
  return divu10(x*3);
}

unsigned divu10(unsigned n) {
  unsigned q, rem;
  q = (n >> 1) + (n >> 2);
  q = q + (q >> 4);
  q = q + (q >> 8);
  q = q + (q >> 16);
  q = q >> 3;
  rem = n - q*10;
  return q + ((rem + 6) >> 4);  
}


推荐阅读
author-avatar
YANGYANG.
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有