简体   繁体   English

按位乘法和除法不适用于大数

[英]Bitwise multiplication and division not working with large numbers

I'm trying to get this problem to work where I have to multiply 3/8 in bit and then round towards zero. 我试图解决这个问题,我必须将3/8乘以位,然后四舍五入为零。

So far I have this 到目前为止,我有这个

((((x<<1)+x)>>3)+((x>>31)&1));

The idea behind it is that the first part takes x and shifts it left 1 and adds x to get the multiplied by 3 effect and then shifts right 3 to get the divide by 8 part. 其背后的想法是,第一部分取x并将其向左移动1,再加上x以得到乘以3的效果,然后向右移3以得到除以8的部分。 Then I would add 1 if it is negative by testing to see if the sign bit is 1 (1&1 = 1) or 0 (0&1 = 0). 然后,如果要测试符号位是1(1&1 = 1)还是0(0&1 = 0),则如果它为负数,我将加1。 My code won't work though, the tests are off. 我的代码无法正常工作,测试已关闭。

Any ideas what I am doing wrong? 有什么想法我做错了吗?

The left shifts that you use in effect shifts the individual bits as an unsigned integer so that you could wind up losing the sign bit. 实际上使用的左移会将单个位作为无符号整数进行移位,这样您最终可能会丢失符号位。 That is not what it sounds like you want. 听起来并不是您想要的。 Try the multiplication to see what you should be getting against the bit shift to see what you are getting. 尝试乘法,以了解您在逆转时应该得到什么,以了解您正在得到什么。

x *= 3.0/8.0;

Note the manual entry below showing that if the signed bit is affected the result is undefined 请注意下面的手动输入,其中显示如果有符号位受到影响,则结果不确定

Left shift 左移

The left-shift operator causes the bits in shift-expression to be shifted to the left by the number of positions specified by additive-expression. 左移运算符使移位表达式中的位向左移位加法表达式指定的位置数。 The bit positions that have been vacated by the shift operation are zero-filled. 通过移位操作腾出的位位置为零填充。 A left shift is a logical shift (the bits that are shifted off the end are discarded, including the sign bit). 左移是逻辑移位(从末端移出的位将被丢弃,包括符号位)。 For more information about the kinds of bitwise shifts, see Bitwise shifts. 有关按位移位的种类的更多信息,请参见按位移位。

The following example shows left-shift operations using unsigned numbers. 以下示例显示了使用无符号数字的左移操作。 The example shows what is happening to the bits by representing the value as a bitset. 该示例通过将值表示为位集来显示这些位所发生的情况。 For more information, see bitset Class. 有关更多信息,请参见bitset类。

If you left-shift a signed number so that the sign bit is affected, the result is undefined . 如果左移有符号数以使符号位受影响,则结果是undefined The following example shows what happens in Visual C++ when a 1 bit is left-shifted into the sign bit position. 下面的示例显示将1位左移到符号位位置时在Visual C ++中发生的情况。

#include <iostream>
#include <bitset>
using namespace std;

int main() {
  short short1 = 16384;    
  bitset<16> bitset1{short2};
  cout << bitset1 << endl;  // 0100000000000000 

  short short3 = short1 << 1;
  bitset<16> bitset3{short3};  // 16384 left-shifted by 1 = -32768
  cout << bitset3 << endl;  // 100000000000000

  short short4 = short1 << 14;
  bitset<16> bitset4{short4};  // 4 left-shifted by 14 = 0
  cout << bitset4 << endl;  // 000000000000000  
}

You are overflowing your format by testing with the most negative number and then trying to multiply it to a larger (ie, even more negative) number. 通过使用最大的负数进行测试,然后尝试将其乘以一个更大的(即,甚至更大的负数)数字,您的格式就显得很多余。

There are various ways to fix this. 有多种解决方法。

  1. Use something larger like int64. 使用更大的内容,例如int64。
  2. Use a second value to hold the overflow. 使用第二个值来保持溢出。
  3. Split the value in half and then compute it as a polynomial. 将值分成两半,然后将其计算为多项式。

For the one test case, you could divide first and then multiply, and it would "work", but it would fail for all the cases where you then lose bits off the right side. 对于一个测试用例,您可以先除以然后乘以,这将“起作用”,但是在所有情况下,您都会在右侧丢失一些位而失败。

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

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM