在了解如何在C中实现、
-
、*
和/
等原始运算符时,我从一个有趣的答案中找到了以下片段。
// replaces the + operator
int add(int x, int y) {
while(x) {
int t = (x & y) <<1;
y ^= x;
x = t;
}
return y;
}
这个函数似乎演示了在后台的实际工作方式。然而,这对我来说太让人困惑了,无法理解。很长一段时间以来,我一直相信这样的操作是使用编译器生成的汇编指令来完成的!
运算符是否作为发布在MOST实现上的代码实现?这是否利用了两个的补充或其他与实现相关的特性?
似乎这个函数演示了如何在后台实际工作
不可以。这被转换为本机add
机器指令,它实际上在ALU
中使用硬件加法器。
如果你想知道计算机是如何添加的,这里有一个基本的加法器。
计算机中的一切都是用逻辑门完成的,逻辑门主要由晶体管构成。全加器中有半加器。
有关逻辑门和加法器的基本教程,请参见。这段视频非常有用,虽然很长。
在该视频中,显示了一个基本的半加法器。如果你想要一个简短的描述,就是它:
半加法器加上两位。可能的组合有:
那么半加法器是如何工作的呢?它由三个逻辑门组成,和
,异或
和与非门
。如果两个输入都为负,nand
提供正电流,这意味着这解决了0和0的情况。异或给出一个正输出,一个输入为正,另一个为负,这意味着它解决了1和0的问题。只有当两个输入都为正时,和
才提供正输出,从而解决了1和1的问题。基本上,我们现在有了半加法器。但我们仍然只能添加一些。
现在我们制作全加法器。全加器由一次又一次地调用半加器组成。现在这有一个携带。当我们加1和1时,我们得到一个进位1。所以全加器所做的是,它从半加器获取进位,存储它,并将它作为另一个参数传递给半加器。
如果你不知道如何传递进位,你基本上先用半加法器把位相加,然后再把和和和进位相加。现在你已经添加了进位,两位。所以你一次又一次地这样做,直到你必须添加的部分结束,然后你得到你的结果。
惊讶吗?这就是它实际发生的方式。它看起来像一个漫长的过程,但计算机在几分之一纳秒内完成,或者更具体地说,在半个时钟周期内完成。有时甚至在一个时钟周期内执行。基本上,计算机有ALU
(CPU
的主要部分)、内存、总线等。
如果你想学习计算机硬件,从逻辑门,内存和ALU,并模拟一台计算机,你可以看到这门课程,从中我学到了这一切:从第一原理构建一台现代计算机
如果你不想要电子证书,它是免费的。课程的第二部分将于今年Spring推出
当你加两位时,结果如下:(真值表)
a | b | sum (a^b) | carry bit (a&b) (goes to next)
--+---+-----------+--------------------------------
0 | 0 | 0 | 0
0 | 1 | 1 | 0
1 | 0 | 1 | 0
1 | 1 | 0 | 1
所以如果你按位异或,你可以得到不带进位的总和。如果你按位做,你可以得到进位位。
对多位数a
和b
a+b = sum_without_carry(a, b) + carry_bits(a, b) shifted by 1 bit left
= a^b + ((a&b) << 1)
一旦b
为0
:
a+0 = a
所以算法可以归结为:
Add(a, b)
if b == 0
return a;
else
carry_bits = a & b;
sum_bits = a ^ b;
return Add(sum_bits, carry_bits << 1);
如果你摆脱递归,把它转换成循环
Add(a, b)
while(b != 0) {
carry_bits = a & b;
sum_bits = a ^ b;
a = sum_bits;
b = carrry_bits << 1; // In next loop, add carry bits to a
}
return a;
考虑到上述算法,来自代码的解释应该更简单:
int t = (x & y) << 1;
携带比特。如果两个操作数中右侧的1位均为1,则进位为1。
y ^= x; // x is used now
不带进位的加法(忽略进位)
x = t;
重用x将其设置为携带
while(x)
当有更多进位时重复
递归实现(更容易理解)是:
int add(int x, int y) {
return (y == 0) ? x : add(x ^ y, (x&y) << 1);
}
似乎这个函数演示了如何在后台实际工作
不。通常(几乎总是)整数加法转换为机器指令加法。这只是演示了一个使用按位异或和的替代实现。
为了显得迂腐,C规范没有指定如何实现加法。
但实际上,小于或等于CPU字长的整数类型上的运算符会直接转换为CPU的加法指令,而较大的整数类型会转换为多个加法指令,并带有一些额外的位来处理溢出。
CPU内部使用逻辑电路来实现加法,不使用循环、位移位或任何与C的工作方式非常相似的东西。
本文向大家介绍c#中的三元运算符是?相关面试题,主要包含被问及c#中的三元运算符是?时的应答技巧和注意事项,需要的朋友参考一下 三元运算符,有的也称三目运算符,是对if else 双分支条件语句的简化 格式如下: 表达式一?表达式二:表达式三 释义:如果表达式一为真,就执行问号后边紧跟着的表达式,也就是表达式二; 否则执行冒号后边的表达式,即表达式三。 等价
当我运行这段代码时,我得到以下错误截图 50:7:错误:与“操作员”不匹配
问题内容: 我已经尝试实现sizeof运算符。 但是,对于任何一种数据类型,结果总是以“ 1”表示。 然后,我为此搜索了一下..,我发现代码是 强制转换的 如果代码是强制转换的,那么代码也可以正常工作。.我不明白为什么..该代码也完美地填充了结构。 它也为 有人能解释一下如果进行类型转换和未进行类型转换如何工作吗? 提前致谢.. 问题答案: 指针减法的结果以 元素 为单位,而不是以字节为单位。因此
问题内容: 我正在尝试创建一个无符号整数类。 有没有办法实现诸如 +,-,*,/,<<,>>,|,^,>>>,<< 问题答案: Java不支持运算符重载。你是唯一的选择定义了类似的方法,,,等,并写出逻辑存在,并调用它们的特定操作。 您可以看一下BigInteger类,以了解如何定义支持各种操作的方法。如果有兴趣,您甚至可以浏览源代码,您可以在 jdk 主目录的 src 文件夹中找到该源代码。 _
主要内容:算术运算符,关系运算符,逻辑运算符,位运算符,赋值运算符,其他运算符运算符其实就是一个符号,用来告诉编译器执行特定的数学或逻辑运算。C# 中内置了丰富的运算符,大致可以分为如下几类: 算术运算符; 关系运算符; 逻辑运算符; 位运算符; 赋值运算符; 其它运算符。 下面就来分别介绍一下这些运算符。 算术运算符 算术运算符即完成特定算术运算的符号,C# 中支持的算术运算符如下表所示:(假设变量 A = 10,变量 B = 20) 运算符 描述 实例 + 加法运算符,
运算符是一个符号,告诉编译器执行特定的数学或逻辑操作。 C ++内置丰富的运算符,并提供以下类型的运算符 - 算术运算符 关系运算符 逻辑运算符 按位运算符 分配运算符 其它运算符 本章将逐一检查算术,关系,逻辑,按位,赋值和其他运算符。 算术运算符 (Arithmetic Operators) C ++语言支持以下算术运算符 - 假设变量A保持10,变量B保持20,则 - 显示示例 操作者 描述