整数除法与浮点除法 ->谁负责提供结果?
我已经用 C++ 编程了一段时间,但突然产生了疑问,想向 Stackoverflow 社区进行澄清。
当一个整数除以另一个整数时,我们都知道结果是一个整数,同样,一个浮点数除以浮点数也是一个浮点数。
但谁负责提供这个结果呢?是编译器还是DIV指令?
I've been programming for a while in C++, but suddenly had a doubt and wanted to clarify with the Stackoverflow community.
When an integer is divided by another integer, we all know the result is an integer and like wise, a float divided by float is also a float.
But who is responsible for providing this result? Is it the compiler or DIV instruction?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
这取决于您的架构是否有
DIV
指令。如果您的体系结构同时具有整数和浮点除法指令,编译器将为代码指定的情况发出正确的指令。语言标准指定了类型提升的规则以及在每种可能的情况下是否应使用整数或浮点除法。如果只有整数除法指令或浮点除法指令,编译器将内联一些代码或生成对数学支持库的调用来处理除法。除法指令的速度非常慢,因此大多数编译器都会尽可能地对其进行优化(例如,用移位指令替换,或预先计算编译时常量除法的结果)。
That depends on whether or not your architecture has a
DIV
instruction. If your architecture has both integer and floating-point divide instructions, the compiler will emit the right instruction for the case specified by the code. The language standard specifies the rules for type promotion and whether integer or floating-point division should be used in each possible situation.If you have only an integer divide instruction, or only a floating-point divide instruction, the compiler will inline some code or generate a call to a math support library to handle the division. Divide instructions are notoriously slow, so most compilers will try to optimize them out if at all possible (eg, replace with shift instructions, or precalculate the result for a division of compile-time constants).
硬件除法指令几乎从不包括整数和浮点之间的转换。如果你得到除法指令(有时会被忽略,因为除法电路又大又复杂),它们实际上肯定是“int 除以 int,产生 int”和“除 float 除以 float,产生 float” 。通常输入和输出的大小也相同。
编译器负责在这些原语之上构建源代码中编写的任何操作。例如,在 C 中,如果将 float 除以 int,编译器将发出 int 到 float 的转换,然后发出 float 除法。
(确实存在古怪的异常。我不知道,但我不会把它放在 VAX 之外,以具有“除浮点除以 int”类型指令。Itanium 并没有真正的除法指令,但它的“除法助手” “仅适用于浮点,您必须在浮点除法之上伪造整数除法!)
Hardware divide instructions almost never include conversion between integer and floating point. If you get divide instructions at all (they are sometimes left out, because a divide circuit is large and complicated), they're practically certain to be "divide int by int, produce int" and "divide float by float, produce float". And it'll usually be that both inputs and the output are all the same size, too.
The compiler is responsible for building whatever operation was written in the source code, on top of these primitives. For instance, in C, if you divide a float by an int, the compiler will emit an int-to-float conversion and then a float divide.
(Wacky exceptions do exist. I don't know, but I wouldn't put it past the VAX to have had "divide float by int" type instructions. The Itanium didn't really have a divide instruction, but its "divide helper" was only for floating point, you had to fake integer divide on top of float divide!)
编译器将在编译时根据所使用的变量的类型决定需要哪种形式的除法 - 最终将涉及一种或另一种形式的 DIV(或 FDIV)指令。
The compiler will decide at compile time what form of division is required based on the types of the variables being used - at the end of the day a DIV (or FDIV) instruction of one form or another will get involved.
你的问题确实没有意义。 DIV 指令本身不执行任何操作。无论你对它喊得多么大声,即使你试图贿赂它,它都不会对任何事情承担责任。
当你用编程语言 [X] 编程时,它的唯一责任是[X] 编译器制作一个执行您在源代码中描述的操作的程序。
如果请求除法,编译器将决定如何进行除法。如果您的目标 CPU 有一个操作码,则可能会通过为
DIV
指令生成操作码来实现这一点。它可能是通过在编译时预先计算除法,然后将结果直接插入到程序中(假设两个操作数在编译时已知),或者可以通过生成一系列指令来完成,这些指令一起模拟 一个部门。但这始终取决于编译器。除非根据 C++ 标准进行解释,否则您的 C++ 程序不会产生任何效果。如果您将其解释为纯文本文件,它不会执行任何操作。如果你的编译器将其解释为 Java 程序,它就会阻塞并拒绝它。
而且 DIV 指令对 C++ 标准一无所知。另一方面,编写 C++ 编译器的唯一目的是理解 C++ 标准并根据它转换代码。
编译器始终负责。
Your question doesn't really make sense. The DIV instruction doesn't do anything by itself. No matter how loud you shout at it, even if you try to bribe it, it doesn't take responsibility for anything
When you program in a programming language [X], it is the sole responsibility of the [X] compiler to make a program that does what you described in the source code.
If a division is requested, the compiler decides how to make a division happen. That might happen by generating the opcode for the
DIV
instruction, if the CPU you're targeting has one. It might be by precomputing the division at compile-time, and just inserting the result directly into the program (assuming both operands are known at compile-time), or it might be done by generating a sequence of instructions which together emulate a divison.But it is always up to the compiler. Your C++ program doesn't have any effect unless it is interpreted according to the C++ standard. If you interpret it as a plain text file, it doesn't do anything. If your compiler interprets it as a Java program, it is going to choke and reject it.
And the DIV instruction doesn't know anything about the C++ standard. A C++ compiler, on the other hand, is written with the sole purpose of understanding the C++ standard, and transforming code according to it.
The compiler is always responsible.
C++ 标准中最重要的规则之一是“as if”规则:
与您的问题相关的是,只要完成划分,哪个组件进行划分并不重要。它可以由
DIV
机器代码执行,如果没有适合所讨论的处理器的指令,则可以由更复杂的代码执行。它还可以:
One of the most important rules in the C++ standard is the "as if" rule:
Which in relation to your question means it doesn't matter what component does the division, as long as it gets done. It may be performed by a
DIV
machine code, it may be performed by more complicated code if there isn't an appropriate instruction for the processor in question.It can also:
实际上,
C99 标准定义了“当整数相除时, / 运算符的结果
是任何小数部分的代数商
被丢弃。”并在脚注中添加“这通常被称为‘向零截断’。”
历史
从历史上看,语言规范是负责的。
Pascal 定义其运算符,以便使用
/
进行除法始终返回real
(即使您使用它来除 2 个整数),如果您想要除以整数并获得整数结果,则可以使用div
运算符(Visual Basic 有一个。类似的区别,并使用\
运算符进行整数除法,返回整数结果。)在 C 中,决定通过将整数操作数之一转换为
float 来实现相同的区别
如果您想要浮点结果,按照您在许多 C 派生语言中描述的方式处理整数与浮点类型已成为惯例,我怀疑此惯例可能起源于 Fortran。Practically
The C99 standard defines "When integers are divided, the result of the / operator
is the algebraic quotient with any fractional part
discarded." And adds in a footnote that "this is often called 'truncation toward zero.'"
History
Historically, the language specification is responsible.
Pascal defines its operators so that using
/
for division always returns areal
(even if you use it to divide 2 integers), and if you want to divide integers and get an integer result, you use thediv
operator instead. (Visual Basic has a similar distinction and uses the\
operator for integer division that returns an integer result.)In C, it was decided that the same distinction should be made by casting one of the integer operands to a
float
if you wanted a floating point result. It's become convention to treat integer versus floating point types the way you describe in many C-derived languages. I suspect this convention may have originated in Fortran.