简体   繁体   English

为什么Java会在这种情况下将double类型转换为float类型?

[英]Why will Java convert the double to float type in this situation?

Today, I defined two float variable f1 and f2 .今天,我定义了两个浮点变量f1f2 Then I perform an addition, "+", arithmetic operation and assign to float variable f .然后我执行加法“+”算术运算并分配给浮点变量f

float f1 = 0.5048076923076923F;
float f2 = 0.5048076923076923F;
float f = f1 + f2;

This is the output:这是输出:
在此处输入图像描述

According to this picture, All floating point values ( float and double ) in an arithmetic operation ( +, −, *, / ) are converted to double type: picture source: http://www.mathcs.emory.edu/~cheung/Courses/170/Syllabus/04/mixed.html根据这张图,算术运算( +、-、*、/ )中的所有浮点值( floatdouble )都转换为double类型:图片来源:http: //www.mathcs.emory.edu/~cheung /Courses/170/Syllabus/04/mixed.html
图片

I found an identical question but it hasn't explain why.我发现了一个相同的问题,但没有解释原因。 Why doesn't eclipse have any issue tips?为什么eclipse没有任何问题提示? Is it the reason why the value of "f1 + f2" is a float type?是不是“f1 + f2”的值是float类型的原因? And, why will Java auto convert the double to float type if like the above picture saying?而且,如果像上图所说的那样,为什么Java会自动将double类型转换为float类型? 图片来源:https://www.homeandlearn.co.uk/java/short_float_variables.html

You seem to be saying that there is a conversion to float in the following.您似乎在说下面有一个转换为float

float f1 = 0.5048076923076923F;
float f2 = 0.5048076923076923F;
float f = f1 + f2;

In fact, there is no conversion.事实上,没有转换。 The values are all float .这些值都是float

In particular, the literal 0.5048076923076923F is a float .特别是,文字0.5048076923076923F是一个float The trailing F makes it a float .尾随F使其成为float If you want a double literal, leave off the F or replace it with D .如果您想要一个双字面量,请不要使用F或将其替换为D

When your teacher says "all floating point values are converted to double " he is wrong.当您的老师说“所有浮点值都转换为double ”时,他错了。 The JLS says (in effect) that a numeric primitive operand will be converted to double when the other operand is a double . JLS 说(实际上)当另一个操作数是 double 时,数字原始操作数将被转换为double double If both operands are float , then the operation will performed using single-precision floating point arithmetic.如果两个操作数都是float ,则操作将使用单精度浮点运算执行。

The JLS reference is JLS 5.6.2: Binary Numeric Promotion . JLS 参考是JLS 5.6.2: Binary Numeric Promotion


It has been pointed out that there may be additional conversions happening at the hardware level.已经指出,在硬件级别可能会发生额外的转换。 For example, the JLS says this:例如,JLS 是这样说的:

Within an expression that is not FP-strict, some leeway is granted for an implementation to use an extended exponent range to represent intermediate results;在非 FP 严格的表达式中,允许实现使用扩展的指数范围来表示中间结果; the net effect, roughly speaking, is that a calculation might produce "the correct answer" in situations where exclusive use of the float value set or double value set might result in overflow or underflow.粗略地说,最终效果是,在独占使用浮点值集或双精度值集可能导致上溢或下溢的情况下,计算可能会产生“正确答案”。

However:然而:

  • This is only allowed if the expression is not strictfp .仅当表达式不是strictfp时才允许这样做。
  • These are not the "conversions" that the JLS talks about in JLS 5.6.2.这些不是 JLS 在 JLS 5.6.2 中谈到的“转换”。
  • This still contradicts what the OP's teacher is saying.这仍然与OP老师所说的相矛盾。 He (or she) states that the all floating point calculations are done using double .他(或她)声明所有浮点计算都是使用double完成的。 The JLS states that under certain circumstances , a hardware platform may use extended precision arithmetic (possibly with more precision than 64 bit floating point), and in other circumstances it must not do this . JLS 规定,在某些情况下,硬件平台可能会使用扩展精度算术(可能比 64 位浮点精度更高),而在其他情况下则不能这样做

Your teacher is incorrect, kindly refer him to section 5.6.2 of the Java Language Specification , which states:你的老师是不正确的,请他参考Java Language Specification 的第 5.6.2 节,其中指出:

  • Widening primitive conversion (§5.1.2) is applied to convert either or both operands as specified by the following rules:加宽原语转换(第 5.1.2 节)适用于转换以下规则指定的一个或两个操作数:

    • If either operand is of type double, the other is converted to double.如果任一操作数是 double 类型,则另一个操作数将转换为 double。

    • Otherwise, if either operand is of type float, the other is converted to float.否则,如果任一操作数的类型为浮点型,则另一个将转换为浮点型。

    • Otherwise, if either operand is of type long, the other is converted to long.否则,如果任一操作数是 long 类型,则另一个将转换为 long。

    • Otherwise, both operands are converted to type int.否则,两个操作数都转换为 int 类型。

As you can see, floats are only converted to double if the other operand is a double , not in all cases as your syllabus incorrectly states.如您所见,仅当另一个操作数为 double 时,浮点数才会转换为 double ,而不是在所有情况下,因为您的教学大纲错误地指出。

That is, the sum of two floats is a float, but the sum of a float and a double is a double.也就是说,两个浮点数的和是一个浮点数,但是一个浮点数和一个双精度数的总和是一个双精度数。

PS: And no, Java will never convert a double to a float unless you explicitly ask it to, as in: PS:不,Java 永远不会将 double 转换为 float,除非您明确要求它,如:

float f = (float) Math.PI;

Hi for floating points values JVM uses instructions like this:嗨,对于浮点值,JVM 使用如下指令:

'+' : fadd : pops two floats, adds them, and pushes the float result '+' : fadd : 弹出两个浮点数,将它们相加,然后推送浮点结果
'-' : fsub : pops two floats, subtracts them and pushes the flot result '-' : fsub : 弹出两个浮点数,减去它们并推送浮点结果

similarly for there are other instructions set for other operators like * and / etc.类似地,还有为其他运算符设置的其他指令,如 * 和 / 等。

So as per JVM implementation point of view float + float will result to float.因此,根据 JVM 实现的观点,float + float 将导致浮动。
But float + double will result to double.但是 float + double 会导致加倍。

For more information, you can read chapter 14. Floating-Point Arithmetic of the book "Inside Java Virtual Machine"有关更多信息,您可以阅读“Inside Java Virtual Machine”一书的第 14 章浮点算术

What the other answers are missing is the hardware level.其他答案缺少的是硬件级别。 Floating point processors, in general, convert all operations to double (or quad), and then return the result in the requested precision.浮点处理器通常将所有运算转换为双精度(或四进制),然后以要求的精度返回结果。 The Java specification may not recognize the conversion, but if it uses the floating point hardware then the conversion happens. Java 规范可能无法识别转换,但如果它使用浮点硬件,则会发生转换。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM