当前位置: 首页 > 面试题库 >

声明浮点数,为什么默认类型为double?

关苗宣
2023-03-14
问题内容

我很好奇为什么必须这样声明float文字:

float f = 0.1f;

代替

float f = 0.1;

为什么默认类型是双精度类型,为什么编译器不能通过查看赋值的左侧来推断它是浮点型的?Google仅提供关于默认值的解释,而不是为什么如此。


问题答案:

为什么默认类型是双精度型?

Java语言的设计者最好问这个问题。他们是唯一知道做出语言设计决定的 真正 原因的人。但我希望推理遵循以下几条原则:

他们需要区分两种类型的文字,因为从数学的角度来看,它们实际上的含义是不同的值。

假设他们将“ float”作为文字的默认值,请考虑以下示例

// (Hypothetical "java" code ... )
double d = 0.1;
double d2 = 0.1d;

在上面,dd2实际上将具有不同的值。在第一种情况下,将低float精度double值在分配点转换为较高精度值。但是您无法恢复不存在的精度。

认为 ,这两个语句都合法且含义不同的语言设计是一个错误的想法……考虑到第一个语句的实际含义与“自然”含义不同。

通过按照他们的方式来做:

double d = 0.1f;
double d2 = 0.1;

既合法又意味着不同的事情。但是在第一个语句中,程序员的意图很明确,而第二个语句的“自然”含义就是程序员得到的。在这种情况下:

float f = 0.1f;
float f2 = 0.1;    // compilation error!

…编译器发现不匹配。

我猜测使用浮点数是例外,而不是现代硬件的规则(使用双精度代替),因此在某些时候可以假设用户在编写时打算使用0.1f float f = 0.1;

他们已经 可以
做到这一点。但是问题在于提出了一组有效的类型转换规则,这些规则非常简单,您不需要Java学的学位就能真正理解。0.1在不同的背景下具有不同的意思会令人困惑。考虑一下:

void method(float f) { ... }
void method(double d) { ... }

// Which overload is called in the following?
this.method(1.0);

编程语言设计很棘手。一个领域的改变可能对其他领域产生影响。

更新 以解决@supercat提出的一些问题。

@supercat:鉴于上述重载,将为method(16777217)调用哪个方法?那是最好的选择吗?

我错误地评论了…编译错误。实际上答案是method(float)

JLS这样说:

15.12.2.5。选择最具体的方法

如果可以访问多个成员方法并将其应用于方法调用,则必须选择一个成员方法来为运行时方法分派提供描述符。Java编程语言使用选择最具体方法的规则。

[符号m1和m2表示适用的方法。]

[如果] m2不是通用的,并且m1和m2可通过 严格宽松调用来应用
,并且其中m1具有形式参数类型S1,…,Sn,而m2具有形式参数类型T1,…,Tn,则该类型对于所有i(1≤i≤n,n =
k),对于参数ei,Si比Ti更具体。

以上条件是一种方法可能比另一种方法更具体的唯一情况。

如果S <:T(第4.10节),则对于任何表达式,类型S都比类型T更具体。

在这种情况下,我们是在比较method(float)method(double)它们都是适用于呼叫。由于float<:,double
更具体 ,因此method(float)将被选择。

@supercat:如果例如这样的表达式被int2 = (int) Math.Round(int1 * 3.5)long2 = Math.Round(long1 * 3.5)替换为int1 = (int) Math.Round(int2 * 3)long2 = Math.Round(long1 * 3)

所做的更改看起来无害,但前两个表达式直到613566756或为止都是正确的,后两个表达式25734855013545685592405[上面完全
失败]失败715827882

如果您正在谈论做出改变的人,那么是的。

但是,编译器不会在后面进行任何更改。例如,int1 * 3.5has类型double(将int转换为double),因此最终调用Math.Round(double)

通常,Java算术将隐式地将数字类型从“较小”​​转换为“较大”,而不是从“较大”转换为“较小”。

但是,您仍然需要小心,因为(在您的取整示例中):

  • 整数和浮点数的乘积可能无法以足够的精度表示,因为(例如)a float的精度比a 的精度低int

  • 将结果Math.round(double)转换为整数类型可导致转换为整数类型的最小/最大值。

但是所有这些都说明了编程语言中的算术支持是棘手的,对于一个新手或粗心的程序员来说,不可避免地会遇到一些麻烦。



 类似资料:
  • 问题内容: 当使用Eclipse从表中生成JPA实体时(对于Java EE Developers,它是Juno 4.2),它建议作为我设置为的属性的默认映射类型。 这很烦人,因为我必须将它们全部手动设置。 有人遇到过这种问题并且知道该怎么办吗?这是错误吗?Eclipse Indigo的行为并非如此。 这是来自:(但根据此文件应映射到此文件,必须是错误的文件- 但是如何找出正确的文件?) 我的SQL

  • 我正在标准中寻找对这一事实的正式解释。我找到了3.9.1/9所说的,并试图用该部分给出解释。 第3.9.1/9节,N3797: void类型有一组空值。void类型是不完整的类型,无法完成。它用作不返回值的函数的返回类型。任何表达式都可以显式转换为cv void类型(5.4)。void类型的表达式只能用作表达式语句(6.2)、逗号表达式的操作数(5.18)以及?的第二个或第三个操作数:(5.16)

  • 这样一个看似简单的数字怎么会“太大”而无法在64位内存中表达呢?

  • 问题内容: 目前,我正在研究Sams出版的《 24小时自学Android应用程序开发》一书。我是Java,Android或其他方面的新手。我在ActionScript 3中具有非常扎实的背景,该语言与Java具有足够的相似性,因此该语言本身并不难掌握,但对于本书中某些代码示例的基本原理,我仍然存在一些疑问。例如,以下是第9小时的示例代码随附的函数: 在此函数签名中,作者已将scoreTable参数

  • 问题内容: 为什么即使该类中没有抽象方法,也将类声明为抽象? 问题答案: 这是因为它遵循模板方法设计模式。这些方法具有返回HTTP 405 未实现方法 错误的所有默认行为。如果所有这些方法都是抽象的,那么即使您的业务需求根本不需要它们,也将不得不覆盖所有这些方法。这只会导致样板代码和不确定/不直观的行为。

  • 我正在讨论以下问题:使用Java 8的可选和stream::FlatMap并希望向自定义的添加一个方法,然后检查它是否工作。 更准确地说,我希望向我的添加一个。如果不存在值,则返回一个空流,如果存在,则返回一个包含单个元素的流。 但是,我得出的结论是,声明为final。 为什么会这样呢?有一些类没有声明为final,我个人认为这里没有理由声明final。 作为第二个问题,为什么不是所有的方法都是f