Java核心技术卷1——运算符 每日笔记

3.5 运算符

运算符用于连接值。

3.5.1算数运算符

  1. 在Java中,使用算术运算符+、-、*、/表示加、减、乘、除运算。

    当参与/运算的两个操作数都是整数时,表示整数除法;

    否则表示浮点数除法。

  2. 整数的求余(取模)操作用%表示。

  3. 可移植性是Java语言的设计目标之一。

    无论在哪个虚拟机上运行,同一运算应该得到同样的结果。

    但是对于浮点数的算术运算来说,实现这样的可移植性是相当困难的。

    • 这是因为普遍double类型使用64位存储一个数值,而有些处理器使用的是80位浮点寄存器。这样寄存器就会增加了中间过程的计算精度。

      例如,以下运算:

      double w = x * y / z;
      

      很多Intel处理器计算 x*y,并且将结果存储在80位的寄存器中,再除以z并将结果截断为64位。(得到更精确的结果)

      但这个结果可能与始终使用64位计算的结果不一样。

      为此,在默认情况下,现在虚拟机设计者允许对中间计算结果采用拓展的精度。

    • 但,对于使用strictfp关键字标记的方法必须使用严格的浮点计算来生成可再生的结果。

      例如,将 main方法 标记为

      public static strictfp void main(String[] args)
      

      那么,在main方法中的所有指令都将使用严格的浮点计算。

    • 如果将一个类标记为strictfp,那么该类中的所有方法都使用严格的浮点计算。

    • 具体的计算细节,取决于Intel处理器的行为

      在默认情况下,中间结果允许使用拓展的指数,但不允许使用拓展的位数(Intel芯片支持截断尾数时并不损失性能)

      因此,这两种方式仅采用默认方式不会产生溢出,采用严格计算时有可能会产生溢出

    • 对大多数程序来说,浮点溢出不属于大问题。在《Java核心技术卷1》中不适用strictfp关键字。

3.5.2 数学函数与常量

  1. 在Math类中,包含了各种各样的数学函数。

  2. 如计算一个数值的平方根,可使用sqrt方法:

    double x = 4;
    double y = Math.sqrt(x);
    System.out.println(y);
    

    注释:println方法和sqrt方法存在微小的差异。

    ​ println方法处理System.out对象。但是Math类中的sqrt方法并不处理任何对象,被称为静态方法

  3. 使用Math类中的pow方法来进行幂运算:

    double y = Math.pow(x, a);
    

    意为将y的值设置为x的a次幂。

    pow方法有两个double类型的参数,返回结果也是double类型。

  4. floorMod 方法的目的解决有关整数余数的问题。

    如当n是负数时,n%2的结果为-1。

    时钟问题:计算一个时钟时针的位置。这里要做一个时间调整,而且要归一化为0~11之间的数。这很简单:(position + adjustment)% 12。

    不过,如果这个调整为负会怎么样呢?我们可能会得到一个负数。所以要引入一个分支,或者使用((position+ adjustment)%12+12)%12。不管怎样都很麻烦。

    floorMod方法就让这个问题变成容易了。

    floorMod(position + adjustment, 12),总会得到一个0~11之间的数。

    (遗憾的是,对于负除数,floorMod会得到负数结果,不过这种情况在实际很少出现。)

  5. Math类提供了一些常用的三角函数:

    Math.sin
    Math.cos
    Math.tan
    Math.atan
    Math.atan2
    

    还有指数函数以及它的反函数——自然对数以及以10为底的对数:

    Math.exp
    Math.log
    Math.log10
    

    最后,Java还提供了两个用于表示 圆周率 和 e 常量的最接近的近似值:

    Math.PI
    Math.E
    
  6. 提示:不必在数学方法名和常量名前添加前缀“Math”,只要在源文件的顶部加上下面这行代码就可以了。

    import static java.lang.Math.*;
    

    例如:

    System.out.println("The square root of \u03C0 is" + sqrt(PI));
    
  7. 注释:在Math类中,为了达到最佳的性能,所有的方法都是用计算机浮点单元中的例程。

    如果得到一个完全可预测的结果比运行速度更重要的话,那么就应该使用StrictMath类。它实现了“可自由分发的数组库(Freely Distributable Math Library,FDLIBM)的算法(www.netlib.orb/fdlibm),确保在所有平台上得到相同的结果。

  8. 注释:Math类提供了一些方法使整数有更好的运算安全性。如果一个计算溢出,数字运算符只是悄悄地返回错误的结果而不做任何提醒。

    例如,10亿乘以3的计算结果将是-1294967296,因为最大的int值也只是刚刚超过20亿。

    如果调用Math.multiplyExact(1000000000,3),就会生成一个异常。

    你可以捕获这个异常或者让程序终止,而不是允许它给出一个错误的结果然后悄无声息地继续运行。

    另外还有一些方法(addExact、 subtractExact、 incrementExact、decrement 和 negateExact)也可以正确的处理int和long参数。

3.5.3 数值类型之间的转换

  1. 将一种数值类型转换为另一种数值类型。下图是书里给出的数值类型之间的合法转换。

    请添加图片描述

    在图中有6个实线箭头,表示无信息丢失的转换;

    另外有3个虚线箭头,表示可能有精度损失的转换。例如,123 456 789是一个大整数,它包含的位数比float类型所能够表示的位数。当将这个整数转换为float类型时,将会得到正确的大小,但是会损失一些精度。

    int n = 123456789;
    float f = n; //f is 1.23456792E8
    
  2. 当用一个二元运算符连接两个值时(例如 n + f,n 是整数,f 是浮点数),先要将两个操作数转换为同一种类型,然后再进行计算

    • 如果两个操作数中有一个是double类型,另一个操作数就会转换为double类型。
    • 否则,如果其中有一个操作数是float类型,另一个操作数将会转换为float类型。
    • 否则,如果其中有一个操作数是long类型,另一个操作数将会转换为long类型。
    • 否则,两个操作数都将转换为int类型。

3.5.4 强制类型转换

可以看到,在必要的时候,int类型的值将会自动地转换为double类型。但另一方面,有时double也会转换为int。

  1. 在Java中,允许进行这种数值之间的类型转换

    当然,有可能会丢失一些信息。这种可能损失信息的转换要通过**强制类型转换(cast)**来完成。

    强制类型转换的语法格式:在圆括号中给出想要转换的目标类型,后面紧跟待转换的变量名。

    例如:

    double x = 9.997;
    int nx = (int)x;a
    

    实现nx的值为9,因为强制类型转换通过截断小数部分将浮点值转换为整型。

  2. 如果想对浮点数进行舍入运算(四舍五入),以便得到最接近的整数,就需要使用Math.round方法:

    double x = 9.997;
    int nx = Math.round(x);
    

    现在,变量x的值为10。

    在调用round时,仍然会使用强制类型转换(int)。原因是round方法返回的结果为long类型,由于存在信息丢失的可能性,所以只有使用显式的强制类型转换才能够将long类型才能将long类型转换为int类型。

  3. 警告:如果试图将一个数值从一种类型强制转换为另一种类型,而又超过了目标类型的表示范围,结果就会截断成一个完全不同的值。

    例如,(byte)300的实际值为44。

  4. C++注释:不要将boolean类型与任何数值类型之间进行强制类型转换,这样可以发生一些常见的错误。

    在极少数的情况下需要将布尔类型转换为数值类型,可以使用条件表达式 b ? 1: 0。

3.5.5 结合赋值和运算符

  1. 可以在赋值中使用二元运算符,这是一种很方便的简写形式。例如:

    x += 4;
    //等价于
    x = x + 4;
    

    (一般来说,要把运算符放在 = 号右边,如 *= 或 %= )。

  2. 注释:如果运算符的左侧操作数和右侧操作数类型不同,就会发生强制类型转换。

    例如, 如果x是一个int,则以下语句

    x += 3.5;
    

    是合法的,等价于将x设置为(int) (x+3.5)。

3.5.6 自增与自减运算符

  1. 在Java中,借鉴了C和C++中的做法,也提供了自增、自减运算符:n++将变量n的当前值加1,n–则将n的值减1。

  2. 由于自增、自减运算符改变的是变量的值,所以它们不能应用于数值本身。

    例如,4++就不是一个合法的语句。

  3. 前后缀:上面是自增、自减运算的后缀形式。

    实际上,它们还有一种前缀形式:++n。

    两者的相同点是都会使变量值加一或减一。

    但是在表达式中,两者进行的时机不同,前缀形式会先完成加一,而后缀形式会使用变量原来的值后加一。

    int m = 7;
    int n = 7;
    int a = 2 * ++m;  //now a is 16, m is 8
    int b = 2 * n++;  //now b is 14, n is 8
    

    建议不要在表达式中使用++,因为这样的代码很容易让人困惑,而且会带来犯人的bug。

3.5.7 关系和 boolean运算符

Java包含丰富的关系运算符。

  1. 要检测相等性,可以使用两个等号==。例如:3==7 的值为flase。

  2. 另外使用!=检测不相等。例如, 3 != 7 的值为true。

  3. 还有经常使用的 <、 >、 <=、 >=运算符。

  4. 逻辑运算符:Java沿用了C++的做法,&&表示逻辑“与”运算符,||表示逻辑“或”运算符,!表示逻辑“非”运算符。

    注意:

    &&和||运算符是按照“短路”方式来求值的:即如果第一个操作数已经能确定表达式的值,第二个操作数就不必计算了。

    例如:

    expression1 && expression2;
    

    如果我们已知&&的expression1为false,那么结果就不可能为true。因此,第二个表达式就不必计算了。可以利用这一点来避免错误。

    例如,在下面表达式中:

    x != 0 && 1 ;/  x > x+y     //no division by 0
    

    如果x等于0,那么第二部分就不会计算 1/x,不会出现除以零的错误。

    类似的,如果expression1为投入,那么expression1 || expression2就会自动为true,而无须计算第二个表达式。

  5. Java支持三元操作符“ ?:”,这个操作符有时很有用。如果条件为true,下面的表达式:

    condition ? expression1 : expression2;
    

    就为第一个表达式的值,否则计算为第二个表达式的值。

    例如,

    x < y ? x : y;
    

    会返回x和y中较小的一个。

3.5.8 位运算符

  1. 处理整型类型时,可以直接对组成整数的各个位完成操作。

    意味着可以使用掩码技术,得到整数中的各个位。

  2. 位运算符包括

    &(“and”) |(“or”) ^(“xor”) -(“not”)

    这些运算符按位模式处理

    例如,如果n是一个整数变量,而且用二进制表示的n从右边数4位为1,则

    int fourthBitFromRight = (n & 0b1000)/ 0b1000;
    

    会返回1,否则返回0。

    利用&并结合使用适当的2的幂,可以把其他位掩掉,而只留下其中的某一位

  3. 注释:应用在布尔值上时,&和|运算符也会得到一个布尔值。

    这两个运算符和&&与||很相似,不过&和|运算符不采用“短路”方式来求值,也就是说,得到结果之前两个操作数都需要计算。

  4. ">>“和”<<"运算符可以将位模式左移或右移。

    需要建立位模式来完成位掩码时,这两个运算符会很方便:

    int fourthBitFromRight = (n & (1 << 3)) >>3;
    
  5. 还有>>>运算符会用0填充高位,这与>>不同,它会用符号位填充高位。

    注意:不存在<<<运算符。

  6. 警告:移位运算符的右操作数要完成模32的运算(除非左操作数是long类型,在这种情况下需要对右操作数模64)。

    例如,1<<35的值等同于 1 << 3或8。

3.5.9 括号与运算符

下表给出了运算符的优先级。

如果不适用圆括号,就按照给出的运算符优先级次序进行计算。

同一个级别的运算符按照从左到右的次序进行计算

(但右结合运算符除外,如表中所示)

请添加图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/432906.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Laravel Octane 和 Swoole 协程的使用分析二

又仔细研究了下 Octane 源码和 Swoole 的文档&#xff0c;关于前几天 Laravel Octane 和 Swoole 协程的使用分析中的猜想&#xff0c;得到进一步验证&#xff1a; Swoole 的 HTTP Server 启动后会创建一个 master 进程和一个 manager 进程&#xff1b;master 进程又会创建多个…

《UE5_C++多人TPS完整教程》学习笔记26 ——《P27 在线会话测试(Testing An Online Session)》

本文为B站系列教学视频 《UE5_C多人TPS完整教程》 —— 《P27 在线会话测试&#xff08;Testing An Online Session&#xff09;》 的学习笔记&#xff0c;该系列教学视频为 Udemy 课程 《Unreal Engine 5 C Multiplayer Shooter》 的中文字幕翻译版&#xff0c;UP主&#xff0…

山海鲸可视化软件实战:如何制作一个高效的商品销售数据看板

作为一名数据分析师&#xff0c;我经常需要通过各种工具将数据转化为有价值的信息&#xff0c;为公司的决策提供支持。最近&#xff0c;我使用山海鲸可视化软件制作了一个商品销售数据看板&#xff0c;山海鲸可视化是一款可以免费可视化编辑、免费私有化部署的产品。下面&#…

6_怎么看原理图之协议类接口之LCD笔记

首先想一想再前几篇文章讲的协议类的前提 1、双方约定好通信的协议 2、双方满足一定的时序要求 以上第二点又有一些要求&#xff1a; 1&#xff09;弄清2440在这个通信协议中&#xff0c;能设置哪些时序的值&#xff0c;这些值的含义是什么——2440手册 2&#xff09;弄清楚这…

一文详解:Open SSL

Open SSL是 SSL (传输层安全)和 TLS (传输层安全)协议的健壮的开源实现。这些加密协议被广泛用于保护计算机网络上的通信&#xff0c;通过在两个通信应用程序之间提供隐私和数据完整性。从更实际的角度来说&#xff0c;OpenSSL 是一个工具包&#xff0c;其中包含各种命令行实用…

学习JAVA的第十四天(基础)

目录 Collection集合 迭代器遍历 增强for遍历 Lambda表达式遍历 List集合 遍历 数据结构 栈 队列 数组 链表 前言&#xff1a; 学习JAVA的第十三天 Collection集合 Collection的遍历方式&#xff1a; 迭代器&#xff08;不依赖索引&#xff09;遍…

当磁盘无法读取时,这样做能拯救你的数据!

一、遭遇磁盘无法读取的困境 在现代社会中&#xff0c;磁盘已成为我们存储和传输数据的重要工具。然而&#xff0c;当磁盘突然无法读取时&#xff0c;我们可能会面临数据丢失的风险&#xff0c;这无疑是一个令人头疼的问题。磁盘无法读取可能表现为电脑无法识别磁盘、磁盘在读…

基于yolov5的水果新鲜度检测系统,可进行图像目标检测,也可进行视屏和摄像检测(pytorch框架)【python源码+UI界面+功能源码详解】

功能演示&#xff1a; 基于yolov5的水果新鲜度检测系统&#xff0c;系统既能够实现图像检测&#xff0c;也可以进行视屏和摄像实时检测_哔哩哔哩_bilibili &#xff08;一&#xff09;简介 基于yolov5的水果新鲜度检测系统是在pytorch框架下实现的&#xff0c;这是一个完整的…

opengl日记23-opengl文字渲染-渐变色-教程示例

Author: wencoo Blog&#xff1a;https://wencoo.blog.csdn.net/ Date: 23/02/2024 Email: jianwen056aliyun.com Wechat&#xff1a;wencoo824 QQ&#xff1a;1419440391 Details:文章目录 目录正文 或 背景 效果展示 目录 正文 或 背景 前些天发现了一个巨牛的人工智能学习…

华为HQoS配置案例

HQoS基于层次化调度&#xff0c;cpe上支持三级队列&#xff1a; level3流队列&#xff1a;每个用户的同类业务是一个业务流&#xff0c;针对每个用户不同的业务流进行队列调度&#xff0c;流队列一般与业务类型对应&#xff08;EF、AF、BE等&#xff09;。 level2用户队列&…

适用于 Windows 的7大数据恢复软件解决方案

数据丢失是数字世界中令人不快的一部分&#xff0c;它会在某一时刻影响许多计算机用户。很容易意外删除一些重要文件&#xff0c;这可能会在您努力恢复它们时带来不必要的压力。幸运的是&#xff0c;数据恢复软件可以帮助恢复已删除的文件&#xff0c;即使您没有备份它们。以下…

玩转小米:如何取消王者荣耀微信双开默认选择

文章目录 💢 问题 💢🏡 演示环境 🏡💯 解决方案 💯💢 问题 💢 当我们在手机上安装了多个微信(分身)后,在一些软件(例如王者)使用微信登入时会出现让们选择使用哪个微信进行登入,但是有时候我们不小心设置了默认某一个微信登入后,下次就无法出现选择页面…

Codesys 位置式PID闭环控制系统(PID+PWM控制无刷电机)

有关Codesys位置式PID算法公式和源代码,请参考下面文章链接: 1、Codesys位置式PID https://rxxw-control.blog.csdn.net/article/details/131591254https://rxxw-control.blog.csdn.net/article/details/1315912542、博途PLC PWM输出控制 https://rxxw-control.blog.csdn.…

JavaScript 闭包:让你更深入了解函数和作用域

&#x1f90d; 前端开发工程师、技术日更博主、已过CET6 &#x1f368; 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 &#x1f560; 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》 &#x1f35a; 蓝桥云课签约作者、上架课程《Vue.js 和 E…

Mybatis框架相关问题

HashMap相关问题 部分示例代码 Mybatis框架相关问题 一、MyBatis框架是如何实现分页的&#xff1f;二、MyBatis框架里面的缓存机制是怎么回事&#xff1f;一级缓存二级缓存 一、MyBatis框架是如何实现分页的&#xff1f; 分页分为两种&#xff1a; 逻辑分页&#xff1a;将所…

直播美颜SDK开发指南:构建个性化的主播美颜工具

本篇文章&#xff0c;小编将带您深入了解如何构建个性化的主播美颜工具&#xff0c;从而为用户提供更优质的直播体验。 一、美颜技术概述 在开始SDK的开发之前&#xff0c;我们首先需要了解美颜技术的基本原理。美颜技术通常包括肤色检测、人脸检测、特征点定位、滤镜处理等步…

C++ 使用libmodbus通信示例

代码示例 #include <future> #include <iostream> #include <thread>#include <modbus.h>// 寄存器数量 #define TEST_MAX_REGISTERS 100 // 读取寄存器数量 #define TEST_MAX_READ 5int main() {// C 异步auto&& f1 std::async(std::launch…

绘图设计:用Draw.io绘制图形技巧大全(含统一建模语言UML模板)

一、常见UML模板 1.流程图 2.用例图 include是包含关系&#xff0c;extend是扩展关系 简而言之&#xff0c;include是子集指向父集&#xff1b;而extend是扩展用例指向基础用例&#xff08;基础用例可以理解为系统核心功能&#xff0c;扩展用例是可选的&#xff0c;不是必须…

Redis-1

1. Redis 功能强大&#xff0c;持续改进&#xff0c;经久不衰 1.高性能 底层C语言编写&#xff0c;内存数据库&#xff0c;通讯采用epoll非阻塞l/O多路复用机制 2.线程安全 3.功能丰富 数据结构&#xff1a; 基本&#xff1a;String、LIst、HashSet、SortredSet 高阶&…

Covalent Network(CQT)构建 Web3 最大的结构化数据集,开拓AI、安全性和数据质量的融合

人工智能浪潮正在对各行各业进行重塑&#xff0c;随着格局的不断演变&#xff0c; Covalent Network&#xff08;CQT&#xff09;正在成为核心参与者。人工智能以其对庞大的结构化数据集的依赖而闻名&#xff0c;而 Covalent Network&#xff08;CQT&#xff09;的广泛数据集正…