美文网首页算法(第四版)程序员
Java 原始数据类型的计算:运算符重载(Operator Ov

Java 原始数据类型的计算:运算符重载(Operator Ov

作者: 不忘初心2017 | 来源:发表于2017-03-27 18:16 被阅读21次

原文阅读:《算法(第四版)》第一章 第一节:基础编程模型

有没有在面试的时候被问到:下面这几行代码的执行结果是什么?依据是什么?

System.out.println (5/3);

System.out.println ((double)(5/3));

System.out.println (5/3.0);

System.out.println (5.0/3.0);

System.out.println ((int)5/(double)3);

这个问题涉及到的概念有:运算符重载类型转换

对于原始数据类型如int, double, 运算符+, -, *, / 可以用于不同类型数据之间的计算: int + int,  int + double, int / double,此为运算符重载的一种

不同类型之间计算时,先转换成同一类型再进行计算,这就涉及到类型转换,关键是要搞清楚这“同一类型”如何界定。

让我们先来看一下原文作者提到的运算符原则:

The key property of these primitive operations is that, an operation involving values of a given type has a value of that type.

原始数据类型运算的一个关键特性是,参与运算的值是什么类型,其运算结果就是同一类型

这里涉及到两种情况:

1) 参与运算的值都是同一类型,如:

5 / 3 等同于 (int 5) / (int 3),参与运算的值都是 int, 所以其结果类型也应是 int.

5.0 / 3.0 等同于 (double 5) / (double 3), 参与运算的值都是 double, 其结果类型也是 double.

2) 参与运算的值属于不同类型:如

5 / 3.0 等同于 (int 5) / (double 3.0), 其结果应该是多少?什么类型呢?

这里参与运算的值有两种类型:int 和 double。要以哪种类型作为运算结果的类型,这就需要依据类型转换原则了。在Java中会自动转换类型,除非显性指名。其转换规则为:

Numbers are automatically promoted to a more inclusive type if no information is lost.

自动转换为比自身表述范围大的类型。

具体细节请参见官方文档: docs.oracle.com/javase/specs/jls/se7/html/jls-5.html#jls-5.1.4

所以对于 (int 5) / (double 3.0), double 是 64 位 ,int 是 32 位,所以计算的时候会自动将 int 5 转换成 double 5.0, 然后再计算,所以结果便是 double 类型。

明白了输出类型是什么,现在我们再来看开头的问题的答案:

System.out.println (5/3);                         //1

System.out.println ((double)(5/3));          // 1.0

System.out.println (5/3.0);                      // 1.6666666666666667

System.out.println (5.0/3.0);                   // 1.6666666666666667

System.out.println ((int)5/(double)3);     // 1.6666666666666667

新的问题又来了,为什么 5/3 的值是 1 而不是 2? 按常规的四舍五入,5/3~=1.66666..., 四舍五入后应为 2。这便是另外一个原则了:

casting to an int is truncation instead of rounding

至于为什么是粗鲁的截断而不是四舍五入,我还没有弄清楚,如果您知道请帮忙解释一下。我试过其他语言比如Python, 同样的行为,所以猜测也许是计算机语言的某种通用逻辑比如浮点数的特殊性(详见引申思考题),还是各高级语言互相学习达成某种程度的一致?

小结:

原始数据类型运算符重载和类型转换用到的三个原则:

1。参与运算的值是何类型,其运算结果也是该类型

2。自动类型转换时会转换为表述范围大的类型

3。从范围大的类型转换为 int 时会截断小数点后的位数,而非四舍五入。

引申:

上述的几个原则,多数编程语言通用,比如我试过python. 这类通用的原则掌握了便可融会贯通。

引申思考题:

在多数编程语言中,为什么 0.1 + 0.2 不等于 0.3?

在您的IDE中试一下,然后再读读这篇论文:docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html

相关文章

  • Java 原始数据类型的计算:运算符重载(Operator Ov

    原文阅读:《算法(第四版)》第一章 第一节:基础编程模型 有没有在面试的时候被问到:下面这几行代码的执行结果是什么...

  • [Flutter]flutter基础之Dart语言基础(四)

    一、运算符重载 Dart 支持运算符重载,使用 operator 关键字,语法格式为:operator 运算符 ,...

  • 16-高级运算符

    溢出运算符(Overflow Operator) 运算符重载(Operator Overload) Equatab...

  • 2017.9.22

    今天上课主要讲了运算符重载。运算符重载格式:类型名operator运算符(形参表){函数体}operator运算符...

  • 9月22日C++学习总结

    1.运算符重载:运算符重载的格式为:类型名 operator 运算符(形参表){函数体},operator是关键字...

  • Dart语言的运算符重载

    什么是运算符重载(operator overloading) 在软件开发过程中,运算符重载(英语:operator...

  • kotlin中的二元运算符重载

    可重载的二元算术运算符 在kotlin中,重载运算符需要使用operator修饰符,如 在java中调用时,像使用...

  • 2017.9.22

    今天学习的是运算符的重载: 运算符重载: 使用运算符重载的一般格式为: 类型名 operator 运算符(形参表...

  • 9.22 c++ 总结

    运算符重载 1.一般格式为: 类型名 operator 运算符(形参表){函数体} 运行方式:调用函数进行计算,...

  • C++基础-(重载)

    C++基础 重载 哪些运算符可以被重载:::,.,->,*,?:不能被重载 重载操作符的标志(operator) ...

网友评论

    本文标题:Java 原始数据类型的计算:运算符重载(Operator Ov

    本文链接:https://www.haomeiwen.com/subject/bfgrottx.html