我遇到了一个问题,因为我有一个隐含的无符号十六进制数作为字符串,由用户输入提供,需要转换为BigInteger.
由于BigInteger设置了最高阶位 (0x8 / 1000b) 的任何输入的有符号性质,结果数字被视为负数。然而,这个问题不能通过简单地检查符号位并乘以 -1 或由于不尊重基础符号的补码获得绝对值来解决,例如将所有值 0xF* 视为 -1。
以下是一些示例输入/输出
var style = NumberStyles.HexNumber | NumberStyles.AllowHexSpecifier;
BigInteger.TryParse("6", style) == 6 // 0110 bin
BigInteger.TryParse("8", style) == -8 // 1000 bin
BigInteger.TryParse("9", style) == -7 // 1001 bin
BigInteger.TryParse("A", style) == -6 // 1010 bin
...
BigInteger.TryParse("F", style) == -1 // 1111 bin
...
BigInteger.TryParse("FA", style) == -6 // 1111 1010 bin
BigInteger.TryParse("FF", style) == -1 // 1111 1111 bin
...
BigInteger.TryParse("FFFF", style) == -1 …Run Code Online (Sandbox Code Playgroud) 我浏览了 ISA 规范并在互联网上搜索了这个问题的答案,但我找不到它。
在RISC-V ISA中,负数应该用补码还是补码表示?或者,这个决定是留给实施者的吗?
我问的原因是我正在编写一个 RV32I 模拟器,这会影响我在模拟内存中存储负数的方式。
原问题:
正数在一个补码和二进制补码中具有相同的表示。假设它的表示被解释为二进制补码,并且它的加法逆是确定的。现在这个表示被解释为一个补码,并且确定了加法逆。无论是解释为一的补码还是二的补码,结果都是一样的,因为它是一个正数。这个结果和原来的数字有什么关系?
我不知道他说的“这个结果和原来的数字有什么关系”是什么意思。我想我明白他要我们做的过程:
首先取二进制(0101),然后取二进制补码(1011),然后取二进制补码的二进制补码(0100)。接下来是什么?
-2一个人的补充是100000 ... 01
-2两个补码是1000000 ...... 10
-2 >>> 1
Run Code Online (Sandbox Code Playgroud)
根据>>>定义,左侧移位为0
应该是这样的 01000......1,为什么变成0111111..11什么?
我最近一直在研究表示数字的一个补码系统,根据我的理解,数字0有两个变量.有一个负零(-0)和一个正零(+0).
我的问题是,在一个补码架构中,这个异常在C中究竟是如何处理的?C是否区分-0和+0,或者这两种形式都被视为零.
如果在测试零时,+ 0和-0都返回TRUE,那么我想知道如果我们输入-0作为输入,下面的示例代码将如何工作以计算整数中的设置位数.
int bitcount(int x)
{
int b;
for (b = 0; x != 0; b++)
x &= (x-1);
return b;
}
Run Code Online (Sandbox Code Playgroud)
由于-0,在一个补码中,其所有位都设置为1,-0应该返回由任何其他数字设置的最高位数; 但是,看起来这个代码会使循环测试条件失败x != 0,甚至不会进入循环,从而产生不正确的结果.
在C语言中,在一个补码架构中,是否有可能使循环条件对正零敏感,如下所示:x != +0另外,如果我从+0中减去1,我会得到-0或-1.换句话说,在一个补码架构中,+ 0 - 1 = -0?
总而言之,在本次讨论中不要偏离太远,我只是想知道C如何处理一个补码架构中数字0的特殊性.
请考虑以下代码:
uint32_t x = ~uint8_t(0);
std::cout << x << std::endl;
Run Code Online (Sandbox Code Playgroud)
现在,我完全期望这个输出255,而是输出4294967295.
我知道C++中的整数提升,但我不明白为什么会这样.我理解它的方式,表达式~uint8_t(0)应该以1111 1111二进制形式进行评估.然后,~操作符将使类型被提升为int(为了讨论,我将假设为32位),通过符号将值扩展为0000 0000 0000 0000 0000 0000 1111 1111.然后应将此提升的值分配给左值x,从而产生x == 255.
但显然我并没有正确理解这一点.我错过了什么?
标题真的说明了一切:减一和蒂尔达(一补)零之间有什么区别?
在讨论指定所有位都设置的位掩码的最佳方法时出现了这个问题.以下哪项更好?
int func(int value, int mask = -1) {
return (value & mask);
}
Run Code Online (Sandbox Code Playgroud)
要么
int func(int value, int mask = ~0) {
return (value & mask);
}
Run Code Online (Sandbox Code Playgroud)
是否还有其他任何用途?
更新:在stackoverflow.com/q/809227/34509上有关于此主题的类似讨论,我在之前的研究中遗漏了这个问题 .感谢Johannes Schaub指出它.
计算二进制补码绝对值的最快方法是一种足够常见的操作,优化的实现已广泛使用。那么让我们考虑另一种情况。如果我们想使用 x86 汇编获取补码的绝对值怎么办?
我拥有的一个快速但可能不是最理想的无分支实现是通过与 10000.... 掩码和移位来获取符号位,将其与 11111... 掩码相乘,然后将其与原始数字进行异或。但有更好的方法吗?
出现这种情况的一个应用是格雷解码的最佳实现。64 位整数的格雷解码的常见实现使用六个异或运算和六个位移位。然而,数字与......1111110 的无进位乘法将给出格雷解码或其按位求反,并取其补码abs 值给出格雷解码。只要可以进行微优化,它就应该比最普遍的方法更快。出于该问题的目的,起始状态可以假定为任何标准 C 调用约定或 CLMUL 操作之后(采用非进位输出)。