`
bencode
  • 浏览: 109342 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

收藏文章一篇(http://www.concentric.net/~Ttwang/tech/javafloat.htm)

阅读更多

Java Floating-Point Number Intricacies

Thomas Wang, March 2000last update September 2000

Abstract

The semantic of Java floating point number generally follows the IEEE 754 Binary Floating-Point Arithmetic standard. The IEEE 754 standard provides for the definitions of floating-point infinities, negative infinities, negative zero, and NaN (not a number). In the context of Java, these entities are often confusing to typical programmers.

In this article, we will discuss the results of computing with these special floating-point entities. We will also point out some common Java floating-point number pit falls.

Introduction

The Java programming language provides two built-in classes for representing floating-point numbers: float, and double. The "float" class takes 4 bytes of storage, and have 23 binary digits of precision. The "double" class takes 8 bytes of storage, and have 52 binary digits of precision.

3.0d is a double precision floating-point number constant. 3.0, or alternatively 3.0f is a single precision floating-point number constant.

float f = 3.0f;
double d = 3.0d;

The Java core library also provides two wrapped classes java.lang.Float, and java.lang.Double. These two classes allow floating-point objects to be stored in Java collection objects, such as hash tables. These two classes also provides parsing, and conversion helper methods.

Float ff = new Float(1.0f); // creates a Java "Float" object
Double dd = new Double(2.0d); // creates a Java "Double" object

Special Floating-Point Number Entities

Not A Number

"NaN" stands for "not a number". "Nan" is produced if a floating point operation has some input parameters that cause the operation to produce some undefined result. For example, 0.0 divided by 0.0 is arithmetically undefined. Taking the square root of a negative number is also undefined.

0.0 / 0.0   ->  NaN
Math.sqrt(-2.0) -> NaN

Operations involving NaN

Double.NaN + Double.NaN  ->  NaN
Float.NaN + 2.0 -> NaN
Float.NaN * 3.0 -> NaN
(0.0 / 0.0) * Float.POSITIVE_INFINITY -> NaN
Math.abs(0.0 / 0.0) -> NaN
(int) (Double.NaN) -> 0

All boolean operations involving "NaN" results in a false value.

Double.NaN > 1.0  ->  false
Double.NaN < 1.0 -> false
Double.NaN == 1.0 -> false
Float.NaN < -3.0 -> false
Float.NaN > Float.POSITIVE_INFINITY -> false
Float.NaN < Float.POSITIVE_INFINITY -> false
(0.0 / 0.0) == (0.0 / 0.0) -> false

Infinity

"Infinity" is produced if a floating point operation creates such a large floating-point number that it cannot be represented normally. "Infinity" is a special value that represent the concept of positive infinity.

1.0 / 0.0  ->  Infinity

Operations Involving Infinities

Double.POSITIVE_INFINITY == Double.POSITIVE_INFINITY  ->  true
Float.POSITIVE_INFINITY == Float.POSITIVE_INFINITY -> true
(1.0 / 0.0) + 2.0 -> Infinity
(1.0 / 0.0) * 0.5 -> Infinity
(1.0 / 0.0) * 0.0 -> NaN
(1.0 / 0.0) + (1.0 / 0.0) -> Infinity
(1.0 / 0.0) * (1.0 / 0.0) -> Infinity
(1.0 / 0.0) - (1.0 / 0.0) -> NaN
(1.0 / 0.0) / (1.0 / 0.0) -> NaN
(int) (1.0 / 0.0) -> 2147483647

Negative Infinity

"-Infinity" is produced if a floating point operation creates such an extremely negative floating-point number that it cannot be represented normally. "-Infinity" is a special value that represent the concept of negative infinity.

-1.0 / 0.0  ->  -Infinity

Operations Involving Negative Infinity

- Double.POSITIVE_INFINITY == Doublle.NEGATIVE_INFINITY  ->  true
Float.NEGATIVE_INFINITY < 1.0 -> true
(-1.0 / 0.0 ) + 2.0 -> -Infinity
(-1.0 / 0.0) == (-1.0 / 0.0) -> true
(-1.0 / 0.0) - (-1.0 / 0.0) -> NaN
(-1.0 / 0.0) * 0.5 -> -Infinity
(-1.0 / 0.0) * 0.0 -> NaN
Math.abs(-1.0 / 0.0) -> Infinity
(int) (-1.0 / 0.0) -> -2147483648

Negative Zero

"-0.0" is produced when a floating-point operation results in a negative floating-point number so close to 0 that cannot be represented normally.

-2.0 / Float.POSITIVE_INFINITY  ->  -0.0

"-0.0" is numerically identical to "0.0". However, some operations involving "-0.0" are different than the same operation with "0.0".

(-0.0) == 0.0  ->  true
2.0 / (0.0) -> Infinity
2.0 / (-0.0) -> -Infinity

Operations Involving Negative Zero

0.0 > (-0.0)  ->  false
(-0.0) * (-0.0) -> 0.0
3.0 + (-0.0) -> 3.0
4.0 * (-0.0) -> -0.0
0.0 - 0.0 -> 0.0
(-0.0) - (-0.0) -> 0.0
(-0.0) + (-0.0) -> -0.0
(-0.0) + 0.0 -> 0.0
0.0 + (-0.0) -> 0.0
(-0.0) - 0.0 -> -0.0
- (-0.0) -> 0.0
- (0.0) -> -0.0
0.0 / (-0.0) -> NaN

Comparing Java "Float" Objects

Comparing two Java "Float" objects can have different semantics than comparing two Java "float" values. Recall the "float" class is a Java primitive class, while java.lang.Float is a subclass of "Object".

A "NaN" value is not equal to itself. However, a "NaN" Java "Float" object is equal to itself. The semantic is defined this way, because otherwise "NaN" Java "Float" objects cannot be retrieved from a hash table.

(new Float(0.0 / 0.0)).equals(new Float(0.0 / 0.0))  ->  true

For the class java.lang.Float, objects are ordered from lowest to highest: -Infinity, negative numbers, -0.0, 0.0, positive numbers, Infinity, NaN. "java.lang.Double" objects are identically ordered.

(new Float(0.0)).equals(new Float(-0.0))  ->  false

(new Float(-1.0 / 0.0)).compareTo(new Float(-3.0)) -> -1
(new Float(-3.0)).compareTo(new Float(-0.0)) -> -1
(new Float(-0.0)).compareTo(new Float(0.0)) -> -1
(new Float(0.0)).compareTo(new Float(3.0)) -> -1
(new Float(3.0)).compareTo(new Float(1.0 / 0.0)) -> -1
(new Float(1.0 / 0.0)).compareTo(new Float(0.0 / 0.0)) -> -1

Some Actual Pitfalls

Wrong Way to Implement abs()

This is the wrong way:

(f >= 0.0) ? f : - f

What if 'f' is -0.0? Since 0.0 is equal to -0.0, the above expression would return the incorrect value of -0.0, versus the correct value of 0.0.

The correct expression is:

(f <= 0.0) ? 0.0 - f : f

Be very careful when you are optimizing a floating point expression. For example, if you optimized the above expression to:

(f <= 0.0) ? - f : f

Then you introduced a bug that causes abs(0.0) to return -0.0.

Danger of Floating-Point Number Optimization

We have already seen a case where (0.0 - f) is not equal to (- f).

! (a < b) does not imply that (a >= b).

! (1.0 < NaN)  ->  true
(1.0 >= NaN) -> false

One page 308 of the book "The Java Language Specification", it talks in more detail of the danger of optimizing floating-point expressions.

Assuming A Floating-Point Value Is Equal To Itself

Well, a "NaN" value is not equal to itself. For similar reason, assuming a number subtracting itself must equal to 0.0 is wrong. "NaN" - "NaN" still yields "NaN". "Infinity" - "Infinity" yields "NaN", although two Infinities are equal to each other.

Not Checking for NaN

public employee(float monthly_salary)
{
if (monthly_salary < 0.0)
throw IllegalArgumentException("illegal monthly salary");
this.yearly_salary = 12.0 * monthly_salary;
}

The above piece of code would not catch the mistake of using a "NaN" as an input argument. The code below would catch it.

public employee(float monthly_salary)
{
if (monthly_salary >= 0.0)
{
this.yearly_salary = 12.0 * monthly_salary;
}
else throw IllegalArgumentException("illegal monthly salary");
}

Looking at the fixed code, what should we do if the input argument is "Infinity"? Depending on the API's specification, we can do a number of different things. The point is that any time we are dealing with floating-point numbers, we should think about the cases dealing with "NaN", "Infinity", "-Infinity", and "-0.0".

References

James Gosling, Bill Joy, Guy Steele, "The Java Language Specification", Addison Wesley, (1996)

IEEE, "ANSI/IEEE Std 754-1985, An American National Standard IEEE Standard for Binary Floating-Point Arithmetic", (1985)

分享到:
评论

相关推荐

    stylelint-config-concentric-order:根据 Concentric CSS 规则验证(和修复)CSS 属性排序的 stylelint 配置

    stylelint-config-concentric-order 此配置根据验证 CSS 属性的顺序。 除了您自己的规则(或来自可共享配置的规则)之外,强烈建议您使用它,因为它只与排序有关。 该配置适用于stylelint --fix和以自动对您的 CSS ...

    flutter-concentric-transition:Flutter插件,可使用同心过渡效果创建视图

    将其导入到您的文件中import 'package:concentric_transition/concentric_transition.dart'; 特征 同心PageView 同心飞剪机 同心PageRoute 用法 使用ConcentricPageView小部件 import 'package:concentric_...

    大学英语六级翻译练习:市场多元化战略.docx

    【市场多元化战略】是企业在市场竞争中采取的一种策略,旨在通过扩展到不同的行业或领域来分散风险、扩大市场份额和实现持续增长。这种战略的核心是企业利用自身的技术、资源和能力,进入与现有业务相关或完全不相关...

    如何使用ping和tracert命令检测丢包

    3 7 ms 7 ms 7 ms x130.cd9e68.sj.concentric.net [205.158.104.130] 4 7 ms 7 ms 8 ms ge9-0.dcr2.dc-fremont-ca.us.xo.net [205.158.60.169] 5 7 ms 7 ms 7 ms ge2-0.dcr1.dc-fremont-ca.us.xo.net [65.106.2.205]...

    matlab跳过代码直接运行-adaptive-risk-appetite:适应性风险偏好

    matlab跳过代码直接运行适应性风险偏好 从以下位置安装:并按照自述文件中的...此示例在同心环世界中演化了一个64千机器人群的行为,可以轻松替代其他世界或行为。基本用法包括: 为包含所有要演化的变量的行为编写脚

    英语中常用的前缀和后缀

    #### 一、常用前缀 **1. micro-:极其小** - **定义与含义**:前缀“micro-”来源于希腊语,意为“极其小”,用于表示极小或微小的事物。 - **示例**: - **computer** → **microcomputer**:微型计算机 - **...

    数学的英语单词(.doc

    - Concentric Circles: 同心圆 - Cone: 圆锥 - Congruent: 全等 - Consecutive Integers: 连续整数 - Coordinate: 坐标 - Cost: 成本 - Counterclockwise: 逆时针 - Cube: 立方体 - Cylinder: 圆柱 - ...

    网络图cytoscape.js

    Cytoscape.js 是一个强大的JavaScript库,专为在Web浏览器中创建交互式网络图谱而设计。这个库被广泛应用于数据可视化、生物信息学、社交网络分析以及其他领域,允许开发者构建复杂的图形界面来展示节点和边的关系。...

    patchwork地面分割原理

    Patchwork 地面分割原理是基于 concentric zone 模型和 Region-wise 地面拟合的ground segmentation 方法,该方法可以 robust 地处理under-segmentation 问题,并且可以在 40Hz 以上的频率下运行。该方法首先将点云...

    CCTag:检测由同心圆组成的CCTag标记

    CCTag库 检测由同心圆组成的CCTag标记。 在CPU和GPU中均实现。 该库是该文件的实现: Lilian Calvet,Pierre Gurdjos,Carsten Griwodz,Simone Gasparini。 在高度挑战性的条件下对圆形基准的检测和精确定位。...

    蚂蚁金服 G6 API 文档.pdf

    G6提供了多种布局算法,包括Force、Fruchterman、Circular、Radial、Dagre、Concentric、Grid、Tree等。开发者可根据具体需求选择合适的布局,并在图初始化后通过`graph.changeLayout`方法更换布局。 ```javascript...

    patchwork论文解读

    《Patchwork:基于同心区域的区域级地面分割与地表概率估计》是一篇发表在2021年10月IEEE ROBOTICS AND AUTOMATION LETTERS上的论文,作者包括Hyungtae Lim、Minho Oh和Hyun Myung。该论文主要探讨了地面分割问题,...

    ASTM B228.pdf

    ASTM B228 是一种标准规范,旨在规定 concentric-lay-stranded 铜包钢导线的生产和检测要求。该标准涵盖了铜包钢导线的材料、结构、性能和检测等多个方面。 1. 范围 ASTM B228 规定了 concentric-lay-stranded 铜...

    concentric-clock:使用C ++和SFML构建的时钟的非常规表示形式

    运行: ./bin/concentric-clock_dbg Windows(在Win7 x64上测试) 将放在文件夹.\lib\ [可选]将SFML .dll文件放在.\bin目录中,以便更轻松地执行二进制文件,因为lib是动态链接的。 如果使用的是mingw32,请运行...

    ASTM B232.pdf

    ASTM B232是一份关于 concentric-lay-stranded 铝导体的标准规范,该规范涵盖了铝导体的设计、制造、测试和应用等方面。 1. 标准规范的作用域 ASTM B232规范涵盖了 concentric-lay-stranded 铝导体的设计、制造和...

    concentric_wheel

    concentric_wheel

    ConCentric Event Planning Software-开源

    ConCentric事件计划软件是一款专为会议和活动策划者设计的开源工具,旨在优化和简化整个活动策划过程。开源软件的特性使得用户可以免费获取、使用,并可以根据自己的需求进行定制和改进,这为用户提供了极大的灵活性...

    抽象精品ppt模板concentric_wheel147

    抽象精品ppt模板concentric_wheel147

    管件中英文对照.doc

    1. **等径直通(Equal Coupling)**:用于连接两个相同直径的管道,提供一个连续的流体通道。 2. **异径直通(Reducing Coupling)**:连接不同直径的管道,允许流体在不同尺寸之间过渡。 3. **牙直通(Female ...

Global site tag (gtag.js) - Google Analytics