我已经使用C++编程一段时间了,但突然有一个疑问,想要向Stackoverflow社区澄清。
当一个整数被另一个整数除时,我们都知道结果是一个整数,同样地,一个浮点数被另一个浮点数除也是一个浮点数。
但是谁负责提供这个结果呢?是编译器还是DIV指令?
我已经使用C++编程一段时间了,但突然有一个疑问,想要向Stackoverflow社区澄清。
当一个整数被另一个整数除时,我们都知道结果是一个整数,同样地,一个浮点数被另一个浮点数除也是一个浮点数。
但是谁负责提供这个结果呢?是编译器还是DIV指令?
这取决于你的架构是否 有 DIV
指令。如果你的架构同时具有整数和浮点数除法指令,编译器将为代码指定的情况发出正确的指令。语言标准指定了类型提升的规则以及在每种可能的情况下应该使用整数或浮点数除法。
如果你只有一个整数除法指令或仅有一个浮点除法指令,则编译器将内联一些代码或生成调用数学支持库来处理除法。除法指令通常很慢,所以大多数编译器会尽可能地优化它们(例如,用移位指令替换,或预计算编译时常量的除法结果)。
编译器将根据所使用变量的类型在编译时决定需要使用哪种形式的除法 - 最终,某种形式的DIV(或FDIV)指令将被引入。
float x = 1.0/3.0
可能会被编译器评估,也可能会产生FDIV - 由编译器决定。 - MSaltersC++标准中最重要的规则之一是“仿佛”规则:
本国际标准中的语义描述定义了一个参数化的非确定性抽象机。本国际标准对符合要求的实现结构没有任何要求。特别地,它们不需要复制或模拟抽象机的结构。相反,符合要求的实现需要模拟(仅)下面解释的抽象机的可观察行为。
这意味着与您的问题相关的是,无论哪个组件执行除法,只要完成即可。它可以通过DIV
机器码执行,如果处理器没有适当的指令,则可以通过更复杂的代码执行。
它还可以:
if(true == false)
这样的事情来欺骗编译器让你编译)。对于编译器产生非标准化警告,这肯定是合理和有用的。 - Jon Hannax/2.5
替换为 x * 0.4
。实际上,这是很常见的,因为乘法通常比除法更快。 - MSaltersC99标准定义了“当整数相除时,/运算符的结果是代数商,任何小数部分都被舍弃。”并在脚注中补充说,“这通常被称为‘向零截断’”。
从历史上看,语言规范负责定义其运算符。
Pascal 定义其运算符,使使用/
进行除法运算始终返回一个real
(即使您用它来除以2个整数),如果要除以整数并获得整数结果,则使用div
运算符。(Visual Basic也有类似的区别,并使用\
运算符进行整数除法运算,返回整数结果。)
在C中,决定通过将整数操作数之一转换为float
来进行相同的区分,如果您想要浮点结果。在许多源自C的语言中,按照您描述的方式处理整数与浮点类型已成为惯例。我怀疑这种惯例可能起源于Fortran。