为什么运算符的操作数需要是同一类型?
Why the operands of an operator needs to be of the same type?
如果我有这样的东西:
int i = 123;
float f = 123.1;
if (f > i) {} else {}
将i
提升为float
,比较会变成if (float > float)
。我的问题是为什么首先需要将 int
变量提升为 float
,是不是因为计算机比较两个纯数字比试图找出其中的位更容易每个数字代表然后比较那个?
因为"There are no numbers"。计算机不比较数字,也不处理数字。他们使用并比较 位模式 。
位模式代表数字的事实是由于 "encoding" 我们用来将数字表示为位模式。一旦我们选择 an 编码,对数字的操作就变成了对位模式的操作。一旦我们选择 another 编码,对数字的相同操作就变成了对位模式的 other 操作。
现在,如果你有 10 种可能的数字表示方式,你应该支持 100 种可能的二进制运算方式(甚至 1000 种,如果你还想考虑结果!)。
因为这不能缩放,所以你必须减少。而更简单的减少方法是通过将它们分成几部分来消除类似的东西:首先将所有数字转换成一个共同的编码,然后对该编码进行操作,最终将结果转换回所需的结果。
这主要是因为对具有相同编码的数字的操作可以很容易地实现,因为相同的规则适用于所有地方,这可以通过[=22=来完成]重复使用相同的电路。
但要使其工作,必须选择 "common format" 以便可以表示两个操作数。并且将 int 表示为 float 比将 float 表示为 int 成功的机会更多。
规则是按原样编写的,因为编译器定义少量执行操作的方式以及规范化操作数的方式比定义大量方式更容易。即使只考虑 int、unsigned int、long、unsigned long、float、double 这六种类型,在不转换操作数的情况下评估像 x < y
这样的表达式也需要特殊情况代码来处理以下情况:
- int/unsigned int(任意顺序)
- long/unsigned长
- int/float
- long/float
- long/double
在 1970 年代,必须为 x > y
处理 16 种不同的操作数类型组合,而不是 6 种,成本过高,尤其是考虑到编译器必须生成更复杂的代码来执行此类比较 "accurately" 比将所有内容都强制为同一类型所需要的要多。
就我个人而言,我认为现代语言设计者应该摆脱 1970 年代的思维模式,但它似乎已经非常成熟(尽管可能还值得注意的是,如果 "long double" 并没有使类型变得无用,该类型在许多平台上已经能够表示每个 long
或 unsigned long
值的值,因此将固定的 float/integer 参数提升为该类型很容易产生语义正确的结果。
如果我有这样的东西:
int i = 123;
float f = 123.1;
if (f > i) {} else {}
将i
提升为float
,比较会变成if (float > float)
。我的问题是为什么首先需要将 int
变量提升为 float
,是不是因为计算机比较两个纯数字比试图找出其中的位更容易每个数字代表然后比较那个?
因为"There are no numbers"。计算机不比较数字,也不处理数字。他们使用并比较 位模式 。
位模式代表数字的事实是由于 "encoding" 我们用来将数字表示为位模式。一旦我们选择 an 编码,对数字的操作就变成了对位模式的操作。一旦我们选择 another 编码,对数字的相同操作就变成了对位模式的 other 操作。
现在,如果你有 10 种可能的数字表示方式,你应该支持 100 种可能的二进制运算方式(甚至 1000 种,如果你还想考虑结果!)。
因为这不能缩放,所以你必须减少。而更简单的减少方法是通过将它们分成几部分来消除类似的东西:首先将所有数字转换成一个共同的编码,然后对该编码进行操作,最终将结果转换回所需的结果。
这主要是因为对具有相同编码的数字的操作可以很容易地实现,因为相同的规则适用于所有地方,这可以通过[=22=来完成]重复使用相同的电路。
但要使其工作,必须选择 "common format" 以便可以表示两个操作数。并且将 int 表示为 float 比将 float 表示为 int 成功的机会更多。
规则是按原样编写的,因为编译器定义少量执行操作的方式以及规范化操作数的方式比定义大量方式更容易。即使只考虑 int、unsigned int、long、unsigned long、float、double 这六种类型,在不转换操作数的情况下评估像 x < y
这样的表达式也需要特殊情况代码来处理以下情况:
- int/unsigned int(任意顺序)
- long/unsigned长
- int/float
- long/float
- long/double
在 1970 年代,必须为 x > y
处理 16 种不同的操作数类型组合,而不是 6 种,成本过高,尤其是考虑到编译器必须生成更复杂的代码来执行此类比较 "accurately" 比将所有内容都强制为同一类型所需要的要多。
就我个人而言,我认为现代语言设计者应该摆脱 1970 年代的思维模式,但它似乎已经非常成熟(尽管可能还值得注意的是,如果 "long double" 并没有使类型变得无用,该类型在许多平台上已经能够表示每个 long
或 unsigned long
值的值,因此将固定的 float/integer 参数提升为该类型很容易产生语义正确的结果。