ISO C标准允许三种编码方法用于有符号整数:二进制补码,一个补码和符号/幅度.
在运行时检测编码的有效或好方法是什么(或者如果有更好的解决方案,还有其他时间)?我想知道这一点,所以我可以针对不同的可能性优化bignum库.
我计划计算这个,并在每次程序运行时将其存储在一个变量中,所以它不必非常快 - 我假设在程序运行期间编码不会改变:-)
我正在编写教程,教孩子们(9到13岁)关于编程.我从计算机本身开始,他们没有那么多与计算机科学有关,而是更多地涉及解决计算问题的过程.
有了这个起点,我指导他们理解机器可以帮助我们解决某些计算问题.人们擅长抽象思维和想象力,但计算机在遵循一个明确规定的例程时非常棒.他们可以一次又一次地以惊人的速度做到这一点!
我的教程已经介绍了以二进制格式表示数字.但是你如何代表负数呢?在任何符号系统中,有很多方法可以做到这一点,但为计算机选择的系统有一个非常特殊的原因:减少添加有符号整数值所涉及的机器数量.我们不希望构建和构建单独的芯片只是为了处理负数,我们想要使用我们用于自然数算术的相同芯片!
如果有人在街上问你(这看起来完全不现实)"计算机如何代表负数,为什么他们用这种方式代表他们呢?"
我的具体问题:
计算机如何代表负数?
为什么计算机以这种方式表示负数?
我猜这个经验丰富的开发人员不得不考虑一下这个问题.有些人甚至可能无法得出答案.我不是想要浮夸,这是来自实际经验,我问过专业开发人员这个问题他们无法回答.他们画了一个空白的凝视.给他们JBoss和JavaBeans,他们会让你充满信心.好笑!我也很难解决这个问题,我每次都要提醒自己,我需要一张纸或白板来制定解决方案.我希望能引导学生更好地了解他们正在使用的机器.
我已经阅读了关于使用两个补码的二进制乘法的这篇文章.但对我来说不是很清楚.即使我很难理解维基文章.我想知道如何计算负数的乘法:
eg: -1 with -7 should give 7.
A 4-bit, 2's complement of -1 is : 1111
A 4-bit, 2's complement of -7 is : 1001
Run Code Online (Sandbox Code Playgroud)
计算乘法的一些逐步方法将是有帮助的.没有我遇到过关于分裂的文章.怎么解决这个问题?
我试图在x86中包围溢出和携带标志.
据我了解,为了添加带符号2的补码数,只能用四种方式之一生成标志(我的例子是4位数):
那么,在x86汇编中,从A中减去B会产生与添加A和-B相同的标志吗?
如果所有值都不超过一个或多个字节,并且没有字节可以包含元数据,那么系统如何跟踪字节所代表的数字类型?在维基百科上查看两个补码和单点揭示了这些数字如何用二进制表示,但我仍然想知道编译器或处理器(不确定我在这里处理的是什么)如何确定这个字节必须是有符号整数.
它类似于接收加密的信件,并且看着我的密码架,想知道要抓住哪一个.有些指标是必要的.
如果我想一下我可以做些什么来解决这个问题,我会想到两个解决方案.我要么声称一个额外的字节并用它来存储描述,要么我会专门为数值表示分配内存部分; 用于签名号码的部分,用于花车的部分等.
我主要在Unix系统上处理C,但这可能是一个更普遍的问题.
假设我有一个最大的32位整数-
const a =
((2 ** 32) - 1)
const b =
parseInt("11111111111111111111111111111111", 2) // 32 bits, each is a one!
console.log(a === b) // true
console.log(a.toString(2))
// 11111111111111111111111111111111 (32 ones)
console.log(b.toString(2))
// 11111111111111111111111111111111 (32 ones)Run Code Online (Sandbox Code Playgroud)
到目前为止,一切都很好。但是,现在让我们说我想使用八(8)个4位数字制作一个32位数字。这个想法很简单:将<<每个4位序列移()到位置,然后将+它们相加()-
const make = ([ bit, ...more ], e = 0) =>
bit === undefined
? 0
: (bit << e) + make (more, e + 4)
const print = n =>
console.log(n.toString(2))
// 4 bits
print(make([ 15 ])) // …Run Code Online (Sandbox Code Playgroud)我有一个十六进制字符串代表一个2的补码数.是否有一种简单的方法(库/函数)将十六进制转换为十进制而不直接使用它的位?
EG这是左侧十六进制给出的预期输出:
"0000" => 0
"7FFF" => 32767 (max positive number)
"8000" => -32768 (max negative number)
"FFFF" => -1
Run Code Online (Sandbox Code Playgroud)
谢谢!
在汇编编程中,想要从寄存器的低位计算某些东西是相当普遍的,这些位不能保证将其他位置零.在像C这样的高级语言中,你只需将输入转换为小尺寸,让编译器决定是否需要分别将每个输入的高位归零,或者是否可以在输出之后切断结果的高位.事实.
这是为x86-64的(又名AMD64),出于各种原因尤其常见1,其中的一些是存在于其它的ISA.
我将使用64位x86作为示例,但目的是询问/讨论2的补码和无符号二进制算法,因为所有现代CPU都使用它.(注意,C和C++不保证两个补码4,并且有符号溢出是未定义的行为.)
作为示例,考虑一个可以编译为LEA指令2的简单函数.(在X86-64 SysV的(Linux)的ABI 3,前两个函数参数是rdi和rsi,与在返回rax. int是一个32位的类型.)
; int intfunc(int a, int b) { return a + b*4 + 3; }
intfunc:
lea eax, [edi + esi*4 + 3] ; the obvious choice, but gcc can do better
ret
Run Code Online (Sandbox Code Playgroud)
gcc知道即使是负有符号整数,加法也只是从右到左,所以输入的高位不会影响进入的内容eax.因此,它保存了一个指令字节并使用 lea eax, [rdi + rsi*4 + 3]
为什么它有效?
1为什么x86-64频繁出现这种情况:x86-64有可变长度指令,其中额外的前缀字节改变了操作数大小(从32到64或16),因此在指令中通常可以保存一个字节.以相同的速度执行.当写入低8b或16b的寄存器(或稍后读取完整寄存器(Intel pre-IvB)时的失速)时,它也具有错误依赖性(AMD/P4/Silvermont):由于历史原因, …
我需要使用二进制补码表示法将有符号整数编码为十六进制.例如,我想转换
e.g. -24375 to 0xffffa0c9.
Run Code Online (Sandbox Code Playgroud)
到目前为止,我一直在研究以下几个方面:
parseInt(-24375).toString(2)
> "-101111100110111"
Run Code Online (Sandbox Code Playgroud)
这与Wolfram Alpha 显示的相匹配,但我不确定如何获得该数字的签名24位int表示(ffffa0c9).
我已经弄清楚如何取无符号二进制数并将其表示为两个补码:
~ parseInt("101111100110111", 2) + 1
> -23475
Run Code Online (Sandbox Code Playgroud)
但我不确定这个数字的二进制表示转换为十六进制.
有任何想法吗?
这很可能是任何人都会问的最愚蠢的问题,但不管我希望我能找到一个明确的答案.
我的问题是 - 整数存储在计算机内存中怎么样?
在c#中,整数的大小为32位.MSDN说我们可以在整数变量中存储-2,147,483,648到2,147,483,647的数字.
根据我的理解,一个位只能存储2个值,即0和1.如果我只能存储0或1,我怎么能在一个位内存储2到9的数字?
更确切地说,我说这个代码int x = 5; 这将如何在内存中表示,或者换句话说如何将5转换为0和1,它背后的惯例是什么?