// 在函数中传递的是基本数据类型 public class Test { public static void main(String[] args) { int a = 3; int b = 4; change(a, b); System.out.println("a=" + a); // 3 System.out.println("b=" + b); // 4 }
public static void change(int i, int j) { int temp = i; i = j; j = temp; } } 结果为:
a=3 b=4
原因:参数中传递的是基本数据类型a和b的拷贝,在函数中交换的也是那份拷贝的值,而不是数据本身。 // 在函数中传的是引用数据类型 public class Test { public static void main(String[] args) { int[] count = { 1, 2, 3, 4, 5 }; change(count); // 6 }
6 原因:在方法中,传递引用数据类型int数组,实际上传递的是该数组的地址值,他们都指向数组对象,在方法中可以改变数组对象的内容。 传递的是对象的引用 class A { int i = 0; } public class Test { public static void main(String args[]) { A a = new A(); add(a); // 1 System.out.println(a.i); // 0 } public static void add(A a) { a = new A(); //如果注释这行,则原值会被修改。 a.i++; System.out.println(a.i); } }
结果为:
1 0
原因:在该程序中,对象的引用指向的是A,而在add方法中,传递的引用的一份副本则指向了一个新的对象,并对新的对象进行操作。而原来的A对象并没有发生任何变化。引用指向的是还是原来的A对象。 // String 不改变,数组改变 public class Example { public static void main(String args[]) { Example ex = new Example(); ex.change(ex.str, ex.ch); System.out.print(ex.str + " and "); // good and System.out.println(ex.ch); // gbc } String str = new String("good"); // good 是常量,不能改 char[] ch = { 'a', 'b', 'c' }; public void change(String str, char ch[]) { str = "test ok"; // test ok 又是一个常量,也不能改 等价于 String str1 = new String("test ok"); ch[0] = 'g'; } }
Correctly compare float or compare double is not only Java specific problem. It can be observed in almost all the programming languages today. In computer memory, floats and doubles are stored using IEEE 754 standard format. How the actual storage and conversion works, it is out of scope of this article.
For now, just understand that during computations and conversions, minor rounding errors can be introduced in these numbers. That’s why it is not advisable to simply rely on the equality operators (==) to compare floating-point numbers.
Let’s learn how to compare float values in Java.
1 2 3 4 5
Table of Contents
1. Simple comparison [Not recommended] 2. Threshold based comparison [Recommended] 3. Compare with BigDecimal [Recommended]
First look at the simple comparison to understand what exactly is wrong with comparing double with == operator. In given program, I am creating same floating point number (i.e. 1.1) using two methods:
Add .1, 11 times.
Multiply .1 to 11.
In theory, both operations should produce the number 1.1. And when we compare the results of both methods, it should match.
f1 = ``1.0999999999999999``f2 = ``1.1``f1 and f2 are not equal
Look at the both values printed in console. f1 is computed to 1.0999999999999999. Its exactly the problem which rounding off causes internally. That’s why, floating point comparison with '==' operator is not recommended.
2. Compare double – Threshold based comparison [Recommended]
Now when we know the problem with equality operator, lets solve it. Using programming, we cannot change the way these floating point numbers are stored or computed. So we have to adapt a solution where we agree that a determine the differences in both values which we can tolerate and still consider the numbers equal. This agreed upon difference in values is called the threshold or epsilon.
So now to use ‘threshold based floating point comparison‘, we can use the Math.abs() method to compute a difference between the two numbers and compare the difference to a threshold value.
1
private` `static` `void` `thresholdBasedFloatsComparison() ``{`` ``final` `double` `THRESHOLD = .``0001``;` ` ``//Method 1`` ``double` `f1 = .``0``;`` ``for` `(``int` `i = ``1``; i <= ``11``; i++) {`` ``f1 += .``1``;`` ``}` ` ``//Method 2`` ``double` `f2 = .``1` `* ``11``;` ` ``System.out.println(``"f1 = "` `+ f1);`` ``System.out.println(``"f2 = "` `+ f2);` ` ``if` `(Math.abs(f1 - f2) < THRESHOLD)`` ``System.out.println(``"f1 and f2 are equal using threshold\n"``);`` ``else`` ``System.out.println(``"f1 and f2 are not equal using threshold\n"``);``}
Program Output.
1
f1 = ``1.0999999999999999``f2 = ``1.1``f1 and f2 are equal using threshold
3. Compare double – Compare with BigDecimal [Recommended]
In BigDecimal class, you can specify the rounding mode and exact precision which you want to use. Using the exact precision limit, rounding errors are mostly solved.
Best part is that BigDecimal numbers are immutable i.e. if you create a BigDecimal BD with value "1.23", that object will remain "1.23" and can never be changed. This class provide many methods which can be used to do numerical operations on it’s value.
You can use it’s compareTo() method to compare to BigDecimal numbers. It ignore the scale while comparing.
a.compareTo(b);
Method returns:
-1 – if a < b)
0 – if a == b
1 – if a > b
Never use the equals() method to compare BigDecimal instances. That is because this equals function will compare the scale. If the scale is different, equals() will return false, even if they are the same number mathematically.
Java program to compare double with BigDecimal class.