有pow()的非浮点替代方法吗?


9

我已经在Arduino网站上搜寻了LANGUAGE REFERENCE,但找不到与Float相当的pow() 东西,就像我必须丢失一些大东西,但是对于我的生命,我感到很沮丧!我pow()在Math标题下的FUNCTIONS列中找到了(就像我期望的那样),但是它说[base]和[exponent]这两个参数都是(浮动的)。在“数学”标题下只有六个其他条目;它们似乎都不是整数版本。我要做的就是使用从0到10的指数生成2的幂。例如2 ^ 0 = 1然后2 ^ 1 = 2然后2 ^ 2 = 4然后2 ^ 3 = 8然后2 ^ 4 = 16然后2 ^ 5 = 32然后2 ^ 6 = 64然后2 ^ 7 = 128然后2 ^ 8 = 256然后2 ^ 9 = 512然后2 ^ 10是1024

使用浮点数是我做到这一点的唯一方法吗?我开始觉得自己与现实背道而驰,实际上已经在计算我的药物治疗了,但是我是正确的。我为造成您浪费时间的这种疏忽大意先向您道歉,但我已经浏览了所有9页标签,并做了我能想到的任何搜索。我承认我并没有花太多时间,但是我确定这只会是五分钟的事情!


2
有关整数pow()的一般情况,请参见stackoverflow.com/questions/101439/…。对于2的幂,只需使用shift。
彼得·科德斯

Answers:


8

对于一般情况,@dat_ha的答案是正确的,但值得注意的是,您需要一个非常特殊的情况... 2的幂。因为计算机使用二进制算术,所以涉及2的幂的运算通常具有一些可用的快捷方式。

将数字乘以2的幂可以通过左移运算(<<)完成,该运算实际上将数字的二进制表示的数字(即位)向左移。在基数2中,向左移一位与乘以2相同,就像在基数10中向左移一位与乘以10一样。有关C ++中左移运算符的完整说明,请参阅有关堆栈溢出的答案

重要的是要注意,左移会丢失信息。移到末尾的位丢失。因为您需要2到10的幂,所以使用带符号整数是安全的,带符号整数在Arduino Uno上具有最大值2^15-1

考虑到这些警告,这里有一个函数可以计算这些约束内的2的幂。这是非常快速的代码,因为左移运算是非常低级的运算,并且实际上不执行乘法运算。

int pow2(int p){
    return 1 << p;
}

错误:如果使用,则最多可以增加2 ^ 32-1 unsigned long
Dat Ha

@DatHa谢谢,我似乎在编辑过程中丢失了“签名”一词。固定。
杰森·克拉克

1
如果您使用任意精度整数算术实现,则可以超过2 ^ 32-1
Dat Han Bag

我想特别想知道为什么对pow()的结果进行整数转换的结果不适用于2的幂。对我来说,pow(2,3)返回8.00,而int(8.00)返回8 ,int(pow(2,3))返回7!
KDM

1

它与intdoublelongfloatunsigned long并且unsigned int应该也可以。您不需要仅使用浮点数。

希望能有所帮助!


上面的答案之所以起作用的原因是因为实数集(包含浮点数)包含整数集
Dat Han Bag

@DatHanBag:更重要的是,每个32位整数都可以用来精确表示double。实际上,由于IEEE浮点是基于二进制尾数/指数表示形式,因此2的每个幂甚至在2 ^ 53(应该double不能表示每个任意整数的点,即1的最后一个单位)处也应可精确表示。尾数大于1.0)。
彼得·科德斯

@PeterCordes是的,我确实知道这一点。在我对答案的评论中,提到arduino的浮点和整数集时,也许我应该说“有界集”
Dat Han Bag

4
对于使用pow()整数的一般问题,这是一个有点有效的答案,但是AFAICT arduino甚至没有硬件浮点,因此这是一个糟糕的答案。像这样的整数pow()实现以log2(n)的时间乘以并累加来累加结果,几乎肯定可以实现更好的性能,而没有提到移位对于2的幂有效,这简直是一个可怕的答案。
彼得·科德斯

1
@PeterCordes“所以这是一个糟糕的答案”。-同意这是一种低质量的简单答案。pow()在log2(n)中肯定是可计算的-这是在学校学到的简单方法(将数本身乘以幂并不那么有效)。例如,对于真正的大整数,您可以使用傅里叶变换来做得更好。但也许OP会接受并喜欢它。
Dat Han手提袋
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.