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

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


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.

  1. 参与运算的值属于不同类型:如

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 Overload)和类型转换(Type Conversion)的更多相关文章

  1. Java语言基础(五) Java原始数据类型的分类以及数据范围

    Java原始数据类型的分类以及数据范围 1.基本数据类型分为:整型(byte, short, int, long),浮点型(float, double),字符型(char),布尔型(boolean) ...

  2. c++ 运算符重载operator

    一般格式为: 函数类型 operator 运算符名称(形参列表){ 对运算符的重载 } 注意函数名是由operator和运算符组成.在上面的一般格式中,operator是关键字,是专门用于重载运算符函 ...

  3. Java 原始数据类型

    如何记住 Java 中的原始数据类型? 画了一个图方便记忆:

  4. swfit:运算符重载 Operator Methods

    Operator Methods Classes and structures can provide their own implementations of existing operators. ...

  5. Java原始数据类型

    Java定义了八种基本类型的数据:byte,short,int,long,char,float,double和boolean. 基本类型通常被称为简单类型.这些基本类型可以分为四组: 整数 - 包括: ...

  6. c++ operator操作符的两种用法:重载和隐式类型转换,string转其他基本数据类型的简洁实现string_cast

    C++中的operator主要有两个作用,一是操作符的重载,一是自定义对象类型的隐式转换.对于操作符的重载,许多人都不陌生,但是估计不少人都不太熟悉operator的第二种用法,即自定义对象类型的隐式 ...

  7. PoEduo - C++阶段班【Po学校】-Lesson03-5_运算符重载- 第7天

    PoEduo - Lesson03-5_运算符重载- 第7天 复习前面的知识点 空类会自动生成哪些默认函数 6个默认函数    1  构造  2  析构   3  赋值  4 拷贝构造  5 oper ...

  8. 《Inside C#》笔记(十一) 运算符重载

    运算符重载与之前的索引器类似,目的是为了让语言本身使用起来更方便直接,也是一种语法糖. 一 运算符重载(Operator Overloading) 运算符重载的存在,使得现有的各种运算符可以被重新定义 ...

  9. C/C++对Lu系统内置动态对象进行运算符重载

    欢迎访问Lu程序设计 C/C++对Lu系统内置动态对象进行运算符重载 1 说明 要演示本文的例子,你必须下载Lu32脚本系统.本文的例子需要lu32.dll.lu32.lib.C格式的头文件lu32. ...

随机推荐

  1. BFC原理

    一.BFC是什么? 在解释 BFC 是什么之前,需要先介绍 Box.Formatting Context的概念. Box: CSS布局的基本单位 Box 是 CSS 布局的对象和基本单位, 直观点来说 ...

  2. 【Java集合类】ArrayList详解 (JDK7)

    相信对于使用过Java的人来说,ArrayList这个类大家一定不会陌生. 数据结构课上讲过, Array是数组,它能根据下标直接找到相应的地址,所以索引速度很快,但是唯一的缺点是不能动态改变数组的长 ...

  3. PMS5003ST+Arduino Nano 串口读取数据

    先上代码: 库文件是在guihub上的大神写的https://github.com/jbanaszczyk,我拿来小改下用以支持5003ST #include <Arduino.h> #i ...

  4. 重磅消息:微信小程序支持长按二维码进入

    之前微信小程序一般通过以下入口进入: 而用户经常使用“长按二维码”识别应用的功能一直未开放,据酷客多了解,微信安卓6.5.6内测版已经支持长按二维码识别和进入小程序,意味着把小程序二维码分享给朋友,或 ...

  5. Android7.0 Phone应用源码分析(四) phone挂断流程分析

    电话挂断分为本地挂断和远程挂断,下面我们就针对这两种情况各做分析 先来看下本地挂断电话的时序图: 步骤1:点击通话界面的挂断按钮,会调用到CallCardPresenter的endCallClicke ...

  6. 谷歌开源图片压缩算法Guetzli实测体验报告

    谷歌大神又出开源新技术啦,这次是对JPEG格式的图片采用全新算法重新编码,输出的图片还是JPEG但是图片大小明显缩小,而质量不但没有损失,甚至还更加优化,速速来体验一把. 一.环境安装 下载谷歌开源软 ...

  7. oracle配置监听图形界面不出来解决方法

    ROOT用户下,执行 xhost +   然后再切换到oracle用户运行netca DISPLAY 在Linux/Unix类操作系统上, DISPLAY用来设置将图形显示到何处. 直接登陆图形界面或 ...

  8. MonkeyRunner之小白如何使用MonkeyRecorder录制回放脚本

    之前摸索了好久.学习Python语言.安装工具.拉拉溜溜也慢慢地一点点进步.每天就疯狂的上网找资料.虽然大牛们写的很详细.但是自己就是笨的不知怎么做.最后找了一篇文章,真的就是万事俱备只欠东风的感觉, ...

  9. Cassandra-java操作——基本操作

    接着上篇博客,我们来谈谈java操作cassandra; 上篇博客的环境:jdk1.7 + python2.7.10 + cassandra2.2.8; 由于2.2.8没有对应的驱动文档,那么我们就用 ...

  10. iOS开发之判断横竖屏切换

    /** *  当屏幕即将旋转的时候调用 * *  @param toInterfaceOrientation 旋转完毕后的最终方向 *  @param duration  旋转动画所花费的时间 */ ...