Java 浮点运算

  可移植性是 Java 语言的设计目标之一, 无论在哪个虚拟机上运行, 同一运算都应得到同样的结果. 但对于浮点数的算术运算, 实现这样的可移植性相当困难. double 类型使用 64 位存出一个数值, 而有些处理器使用 80 位浮点寄存器, 这些寄存器增加了中间过程的计算精度. 比如以下计算:

  double w = x * y / z;

  很多 Intel 处理器计算 x * y, 并将结果存储在 80 为的寄存器中, 再除以 z 并将结果截断为 64 位, 这样可以得到一个更加精确的计算结果, 还能避免产生指数溢出. 但是这个结果可能与始终在 64 位机器上计算的结果不太一样.

  最初的规范规定 Java 虚拟机所有中间计算都必须进行截断, 以保证无论是 80 位寄存器还是 64 位寄存器的浮点计算都能保持完全相同的计算结果, 但这样不仅可能导致溢出, 而且更消耗时间. 为此, Java 承认了最优性能与理想结果之间存在的冲突, 并给予了改进.

  在默认情况下, Java 虚拟机允许对中间计算结果采用扩展的精度(如果处理器支持), 但是对于使用 stricfp 关键字标记的方法必须使用严格的浮点计算来生成可再生的结果. 如可把 main 方法标记为

  public static strictfp void main(String[] args)

  这样, 在 main 方法中的所有指令都将使用严格的浮点计算. 或将一个类标记为 strictfp, 这个类中的所有方法都要使用严格的浮点计算.

  以上, 摘自《Java 核心技术 卷I》, 略有修改.

  总结:

    strictfp, 即 strict float point.

    strictfp 可修饰类或方法, 使之使用严格的浮点计算.

    严格浮点计算不是没有计算结果没有误差, 相反误差可能更大, 且可能会导致溢出和损耗性能.

    若数值计算中不允许有任何舍入误差, 应该使用 BigDecimal 类.

时间: 2024-12-19 15:43:25

Java 浮点运算的相关文章

《深入Java虚拟机学习笔记》- 第14章 浮点运算

<深入Java虚拟机学习笔记>- 第13章 浮点运算

java基础之java程序基础(二)--之浮点运算

整数运算 请点击这里-->>传送门 浮点数运算和整数运算相比,只能进行加减乘除这些数值计算,不能做位运算和移位运算. 在计算机中,浮点数虽然表示的范围大,但是,浮点数有个非常重要的特点,就是浮点数常常无法精确表示. 举个栗子: 浮点数0.1在计算机中就无法精确表示,因为十进制的0.1换算成二进制是一个无限循环小数,很显然,无论使用float还是double,都只能存储一个0.1的近似值.但是,0.5这个浮点数又可以精确地表示. 因为浮点数常常无法精确表示,因此,浮点数运算会产生误差: 浮点数在

JAVA常见面试题及解答-java开发

JAVA常见面试题及解答 Java的垃圾回收总结  浅谈Java中的内部类 1)transient和volatile是java关键字吗? 如果用transient声明一个实例变量,当对象存储时,它的值不需要维持.例如: class T { transient int a;  //不需要维持 int b;  //需要维持 } 这里,如果T类的一个对象写入一个持久的存储区域,a的内容不被保存,但b的将被保存. volatile修饰符告诉编译器被volatile修饰的变量可以被程序的其他部分改变.在多

Java动手及实验整理

1   枚举类型 在Java中,枚举类型本质上其实就是一个类,枚举中的常量都是该枚举类型的实例.枚举类型是引用类型!枚举不属于原始数据类型,它的每个具体值都引用一个特定的对象.相同的值则引用同一个对象.可以使用“==”和equals()方法直接比对枚举变量的值,换句话说,对于枚举类型的变量,“==”和equals()方法执行的结果是等价的. 2 反码.补码原码 原码就是二进制定点表示法,即最高位为符号位,“0”表示正,“1”表示负,其余位表示数值的大小. 反码:正数的反码与其原码相同:负数的反码

【Java】Java_11运算符

1.运算符(operator)  Java 语言支持如下运算符: 算术运算符:  +,-,*,/,%,++ 赋值运算符 = 关系运算符:  >,<,>=,<=,==,!=  instanceof 逻辑运算符:  &&,||,! 位运算符:  &,|,^,~ , >>,<<,>>> 条件运算符 ? 扩展赋值运算符:+=,-=,*=,/= 2.一元运算符(++, --) int a = 3; int b = a++; /

Java中容易被你忽略的细节(一)

1.在一个程序当中代码段访问了同一个对象从单独的并发的线程当中,那么这个代码段叫"临界区" 怎么解决呢:使用同步的机制对临界区进行保护 同步的两种方式:同步块和同步方法 对于同步来说都是使用synchronized方法 每一个对象都有一个监视器,或者叫做锁. java用监视器机制实现了进程之间的异步执行 2.Struts框架基于MVC模式 Struts的工作流程: 在web应用启动时就会加载初始化ActionServlet,ActionServlet从 struts-config.xm

Java关键字:transient,strictfp和volatile简介

关键字:transient 使用对象:字段 介绍:transient说明一个属性是临时的,不会被序列化. 当对象进行序列化(Serializable)过程时候,有一些属性的状态是瞬时的,这样的对象是无法保存其状态的(例如一个Thread对象,或一个FileInputStream对象),对于这些字段,我们必须用transient关键字标明. 将不需要序列化的属性前添加关键字transient,序列化对象的时候,这个属性就不会序列化到指定的目的地中. 关键字:volatile 使用对象:字段 介绍:

《深入Java虚拟机学习笔记》- 第13章 逻辑运算

<深入Java虚拟机学习笔记>- 第13章 浮点运算 <深入Java虚拟机学习笔记>- 第13章 逻辑运算,布布扣,bubuko.com

Core Java 经典笔试题总结(数据类型,表达式问题)

2016-10-18 整理 写一个程序判断整数的奇偶 public static boolean isOdd(int i){ return i % 2 == 1; } 百度百科定义:奇数(英文:odd)数学术语 ,口语中也称作单数, 整数中,能被2整除的数是偶数,不能被2整除的数是奇数,奇数个位为1,3,5,7,9.偶数可用2k表示,奇数可用2k+1表示,这里k就是整数.奇数可以分为: 正奇数:1.3.5.7.9.11.13.15.17.19.21.23.25.27.29.31.33......