Java数学运算符和Math类
Java包含一组内置的数学运算符,用于对Java变量执行简单的数学运算。 Java数学运算符相当简单。因此,Java还包含Java Math类,其中包含用于在Java中执行更高级的数学计算的方法。本章节教程将仔细研究Java的数学运算符以及Java Math类。
Java数学运算符
我先解释一下Java中的四个基本的数学运算符。 Java数学运算符如下:
数据运算符 | 描述 |
---|---|
+ | 加法运算符 |
- | 减法运算符 |
* | 乘法运算符 |
/ | 除法运算符 |
各个运算符的详细内容将在下面小节讲解。
加法
+运算符执行两个值的加法。这两个值可以都是常量,也可以两个变量,还可以是一个常量和一个变量。这里有几个Java的示例:
int sum1 = 10 + 20; // 两个常量相加
int sum2 = sum1 + 33; // 变量与常量相加
int sum3 = sum2 + sum2; // 两个变量相加
+运算符将在运行时用这两个值的总和替换这两个值。所以在表达式sum1 + 33中,在运行时会将被sum1的值和常数值33的和代替。
你当然可以创建更长的加法链,从而加上两个以上的数字。示例如下:
int sum1 = 10 + 20 + 30;
int sum3 = sum2 + 99 + 123 + 1191;
对变量常用的数学运算是将变量设置为自己的值加上另一个值。看起来就像下面这样:
int result = 10;
result = result + 20;
这个例子的第二行赋予变量 result等于它自己的值(在分配新值之前)加上20。也就是10 + 20。
由于变量加上一个值是一个非常常见的操作,因此Java包含一个用于该特定用途的内置操作符。该操作符就是+=运算符。以上示例使用+=运算符重写如下:
int result = 10;
result += 20;
这个例子中的第二行将20加在 result上。相当于result = result + 20;
减法
-运算符是从一个值中减去另一个值。可以是两个常量相减,也可以是两个变量相减,还可以是一个变量减去一个常量。下面是几个Java减法的示例:
int diff1 = 200 - 10;
int diff2 = diff1 - 5;
int diff3 = diff1 - diff2;
-运算符将用这两个值之间的差值替换这两个值,就像使用+运算符一样。
你可以创建更长的减法链,从而减去更多的值。示例如下:
int diff = 200 - 10 - 20;
这点同样适用于变量减法。
记住,负负得正,就像正常的数学运算一样。示例如下:
int diff = 200 - (-10);
在执行这个数学表达式后,diff变量保存的值就是210,因为根据数学规则 -(-10)等于+10。
就像加法一样,Java包含一个专门用于从变量中减去一个值并将结果赋给变量的操作符。这里首先介绍一下如果没有这个操作符如何书写代码:
int result = 200;
result = result - 10;
下面是使用-=运算符的书写形式:
int result = 200;
result -= 10;
乘法
*运算符是两个值相乘的运算。进行乘法运算的值可以是两个常量,一个变量和一个常量值,或者两个变量。示例如下:
int prod1 = 10 * 20;
int prod2 = prod1 * 5;
int prod3 = prod1 * prod2;
*运算符将在运行时将乘法数学表达式替换为两个值的乘积。
你可以使用*运算符创建更长的乘法链。这里是一个乘以3个值的例子:
int prod = 10 * 20 * 30;
将一个变量与一个值相乘并将该值赋给该变量是Java应用程序中常见的数学运算。因此Java包含一个明确的操作符用于这个操作。 *=运算符。如果不使用该运算符代码书写如下:
int result = 10;
result = result * 20;
本示例中的第二行将 result变量的值(在分配此计算结果之前)与20相乘,并将相乘的结果分配 result变量。
使用 *=运算法后,示例如下:
int result = 10;
result *= 20;
除法
/运算符是将一个值除以另一个值。可以是将一个常量与另一个常量相除,可以是一个常量除以一个变量,还可以是用一个变量除以另一个变量。Java的除法示例如下:
int division1 = 100 / 10;
int division2 = division1 / 2;
int division3 = division1 / division2;
你可以对多个值进行连除,但由于Java数学运算符的优先级(稍后解释),所以你必须注意除的顺序的方式。看看以下这个例子:
int division = 100 / 10 / 2;
在执行这个数学表达式之后,变量 division里存储的值是5.因为这个数学表达式是按照首先将100除以10(=10),然后10除以2(= 5)的顺序进行计算的。但是,如果你想实现先进行10除以2(= 5),再进行100除以5(= 20)的运算顺序呢?你可以使用括号来实现,就像下面示例一样:
int division = 100 / (10 / 2)
在本教程中,你将学习更多关于运算符优先级和括号的知识。
Java还包含一个快捷操作符,用于将变量的值除以另一个值,并将该值赋予该变量。 该运算符就是/=运算符。在不使用/=运算符的情况,代码如下:
int result = 100;
result = result / 5;
此示例的第二行将变量 result的值(100)除以5,并将相除的结果重新赋予给变量 result。
使用/=运算符后,代码如下:
int result = 100;
result /= 5;
取模
取模运算将一个值除以另一个值,并返回该除法的余数部分。取模运算的运算符是%(百分号)。下面是一个取模运算的例子:
int value = 100;
int remainder = value % 9;
100除以9商是11,余数1。因此,变量 remainder值为1。
Java还包含一个快捷操作符,%=运算符用于将变量除以另一个值,并将该除法的余数分配给该变量。 示例如下:
int result = 100;
result %= 9;
这个例子的第二行会将 result变量赋值为1。因为100和9进行取模运算等于1。
Java数学运算符优先级
当你开始在Java执行各种数学运算时,控制什么时候执行哪些计算非常重要,从而才能获得所需的结果。 Java数学运算符与标准数学运算符具有相似的自然运算符优先级。
数学运算符和/优先于+和 - 运算符。也就是说,乘法和除法在数学表达式的加减之前被执行。如果有多个和/运算符,它们将从左到右计算。看看下面这个Java数学表达式:
int result = 100 * 100 / 5 + 200 * 3 / 2;
首先执行乘法和除法。有两组三个数的乘、除法分组。每个组从左到右执行:
100 * 100 = 10000;
10000 / 5 = 2000;
200 * 3 = 600;
600 / 2 = 300;
在计算乘法和除法之后,数学表达式就变成了如下所示的样子:
int result = 2000 + 600;
现在执行加法和减法。分配给变量 result的值是2000 + 600 = 2600。
你可以使用圆括号在Java中的数学表达式中控制运算符的优先顺序和计算顺序。括号内的数学表达式比任何其他运算符具有更高的优先级。因此,首先计算括号内的表达式。括号内的运算符优先级和前面介绍的一致。在上一例子中插入圆括号可以改变计算的顺序:
int result = 100 * 100 / (5 + 200) * 3 / 2;
100仍然乘以100(= 10,000),但是现在除数是5+200(=205)而不是5.在该除法之后,结果将乘以3然后除以2.最后得到结果72(计算时四舍五入)。
Java整数运算
在Java整型(byte,short,int和long)上执行的数学运算与正常的数学运算工作方式稍有不同。由于Java整数类型不能包含分数,所以涉及一个或多个整数类型的每个计算都会截断结果中的所有小数。看看这个数学表达式:
int result = 100 / 8;
这个除法的结果是12.5,但是因为这两个数是整数,小数部分.5会被截断,结果就只有12了。
四舍五入也出现在较大计算的过程中,你将在下一节中了解Java浮点运算。
Java浮点数运算
Java包含两个浮点数据类型 float和 double。这些浮点类型能够包含数字中的小数。如果在数学表达式中需要小数部分,就应该使用这些数据类型。这里是一个Java浮点数学运算的例子:
double result = 100 / 8;
即便变量 result现在是一个浮点类型(double),但是最终的结果仍然只是12而不是12.5。原因是表达式中的两个值(100和8)都是整数。因此,将一个整数除以另一个整数,结果首先转换为整数(12),然后分配给变量 result。
为避免Java中数学表达式的计算四舍五入,你必须确保涉及数学表达式的所有数据类型都是浮点类型。例如,你可以先将值分配给浮点变量:
double no1 = 100;
double no2 = 8;
double result = no1 / no2;
现在变量 result就被赋值为12.5;
Java有一种方法可以强制确保计算中的所有数字都是浮点变量。你可以在数字后面加上F或者D来实现。示例如下:
double result = 100D / 8D;
注意每个数字后面的大写字母D。这个大写字母D告诉Java,这些数字将被解释为浮点数,因此进行除法时应该保留小数部分,而不是将其截断。
实际上你也可以用一个大写的L来强制使数字成为长整型数,但 long(长整形)仍然是一个整数类型,所以它计算时仍然不能保留小数。
浮点数精度
Java浮点数据类型不是100%精确的。你可能会经历到有很多小数部分的数字没有达到你所期望的数字的情形。如果一个浮点数的小数位数多于 float或者 double能够表示的范围,那么多余的小数部分会被截断。当然,对于许多类型的计算,给定的精度应该是绰绰有余,但请记住,小数可能被切断。
看看这个Java浮点数计算例子:
double resultDbl3 = 0D;
System.out.println("resultDbl3 = " + resultDbl3);
for(int i=0; i<100; i++){
resultDbl3 += 0.01D;
}
System.out.println("resultDbl3 = " + resultDbl3);
使用Java 8执行此代码时输出如下:
resultDbl3 = 0.0
resultDbl3 = 1.0000000000000007
第一个System.out.println()语句正确输出值0.0,即变量 resultDbl3的初始值。
然而,第二个System.out.println()语句打印出有点奇怪的结果。将0.01自100次应该得到1.0的结果,对不对?但不知为什么,最后的结果是1.0000000000000007。正如你所看到的,不知何故,在小数中出现了一些错误。
通常Java浮点数不精确性是微不足道的,但意识到这一点仍然很重要。
Java Math类
Java Math类提供了比基本Java数学运算符更高级的数学计算。 Math类包含求两个数的最大值或最小值的方法,也提供了舍入值,对数函数,平方根和三角函数(sin,cos,tan等)。
Math类位于java.lang包中,而不在java.math包中。因此,Math类的完全限定类名是 java.lang.Math。
由于 Math类的许多功能是相互独立的,因此每个方法将在下面各自章节中解释。
基本Math函数
java.lang.Math包含一组基本的数学函数,用于获取两个值的绝对值,最大值和最小值,舍入值,随机值等。这些基本数学函数将在以下章节中进行介绍。
Math.abs()
Math.abs()函数返回传递给它的参数的绝对值。如果参数值为负数,则将负号除去,并返回对应于无符号负数的正数值。这里有两个Math.abs()方法的例子:
int abs1 = Math.abs(10); // abs1 = 10
int abs2 = Math.abs(-20); // abs2 = 20
10的绝对值是10,-20的绝对值是20.
Math.abs()方法将在4个类型中被重载:
Math.abs(int)
Math.abs(long)
Math.abs(float)
Math.abs(double)
至于调用哪个方法取决于传递给Math.abs()方法的参数类型。
Math.ceil()
Math.ceil()函数将浮点值向上取整。所得到的值以double形式返回。下面就是一个示例:
double ceil = Math.ceil(7.343); // ceil = 8.0
在执行上面代码后,变量 ceil中的值为8.0
Math.floor()
Math.floor()函数将浮点值向下舍入到最接近的整数值。得到的值以double形式返回。示例如下:
double floor = Math.floor(7.343); // floor = 7.0
在执行上面代码后,变量 floor中的值为7.0
Math.floorDiv()
Math.floorDiv()方法将一个整数(int或long)除以另一个整数,并将结果向下舍入为最接近的整数值。如果结果是正数,则效果与使用/运算符一样。
如果结果是负数,结果是不一样的。使用/除法运算符时,小数将被截断。对于正数,相当于向下取整;对于负数,相当于向上取整。 而floorDiv()方法会向下取整,而不是直接舍掉小数部分。
示例如下:
double result3 = Math.floorDiv(-100,9);
System.out.println("result3: " + result3);
double result4 = -100 / 9;
System.out.println("result4: " + result4);
输出结果如下:
result3: -12.0
result4: -11.0
以上示例展示了/运算符和Math.floorDiv()的区别。
Math.min()
Math.min()方法返回传递给它参数中最小的一个数。示例如下:
int min = Math.min(10, 20);
在执行上面代码后,变量 min中的值为10
Math.max()
Math.max()方法返回传递给它参数中最大的一个数。示例如下:
int max = Math.max(10, 20);
在执行上面代码后,变量 max中的值为20
Math.round()
Math.round()方法使用普通数学舍入规则(向上或向下)将float或double四舍五入为最接近的整数。示例如下:
double roundedDown = Math.round(23.445);
double roundedUp = Math.round(23.545);
在执行上面代码后,变量 roundedDown值为23.0,变量 roundedUp值为24.0
Math.random()
Math.random()方法返回一个介于0和1之间的随机浮点数。当然,这个数并不是完全随机的,但是一些计算的结果应该尽可能地使其不可预测。示例如下:
double random = Math.random();
为了得到0到100之间的随机值,将Math.random()返回的值乘以最大值(例如100)。示例如下:
double random = Math.random() * 100D;
如果你需要一个整数,可以使用 round(), floor() 或者 ceil()方法。
指数和对数函数
Java Math类还包含一组用于指数和对数计算的函数。我将在下面的章节中介绍一些这些数学函数。
Math.exp()
Math.exp()函数返回 $$e^x$$,e是欧拉常数,x为参数。示例如下:
double exp1 = Math.exp(1);
System.out.println("exp1 = " + exp1);
double exp2 = Math.exp(2);
System.out.println("exp2 = " + exp2);
执行后,输出如下:
exp1 = 2.718281828459045
exp2 = 7.38905609893065
Math.log()
Math.log()方法提供了给定参数的对数。对数的基数是e(欧拉数)。因此,Math.log()提供了Math.exp()的相反功能。示例如下:
double log1 = Math.log(1);
System.out.println("log1 = " + log1);
double log10 = Math.log(10);
System.out.println("log10 = " + log10);
输出如下:
log1 = 0.0
log10 = 2.302585092994046
Math.log10()
Math.log10方法的工作方式与Math.log()方法相似,只是使用10作为底数而不是e。示例如下:
double log10_1 = Math.log10(1);
System.out.println("log10_1 = " + log10_1);
double log10_100 = Math.log10(100);
System.out.println("log10_100 = " + log10_100);
输出如下:
log10_1 = 0.0
log10_100 = 2.0
Math.pow()
Math.pow()函数接受两个参数。该方法返回第一个参数为底数,第二个参数为指数的幂,示例如下:
double pow2 = Math.pow(2,2);
System.out.println("pow2 = " + pow2);
double pow8 = Math.pow(2,8);
System.out.println("pow8 = " + pow8);
输出如下:
pow2 = 4.0
pow8 = 256.0
换句话说,上例中计算的是 $$2^2$$ 和 $$2^8$$ ,所得到的结果分别是4和256.
Math.sqrt()
Math.sqrt()方法计算给定的参数的平方根。示例如下:
double sqrt4 = Math.sqrt(4);
System.out.println("sqrt4 = " + sqrt4);
double sqrt9 = Math.sqrt(9);
System.out.println("sqrt9 = " + sqrt9);
输出结果如下:
sqrt4 = 2.0
sqrt9 = 3.0
三角数学函数
Java Math类包含一组三角函数。这些函数可以计算三角函数,如正弦,余弦,正切等。我将在下面的章节中介绍最常用的三角函数。如果你在这里找不到某些三角函数,请查阅Java Math类的JavaDoc。即便我在这里没有提到的一些函数,Java Math类也很有可能提供了。
Math.PI
Math.PI常量是一个 double,它的值非常接近PI的值。进行三角函数计算时,你可能会经常使用Math.PI字段。
Math.sin()
Math.sin()方法以弧度计算某个角度值的正弦值。示例如下:
double sin = Math.sin(Math.PI);
System.out.println("sin = " + sin);
Math.cos()
Math.cos()方法以弧度计算某个角度值的余弦值。示例如下:
double cos = Math.cos(Math.PI);
System.out.println("cos = " + cos);
Math.tan()
Math.tan()方法以弧度计算某个角度值的正切值。示例如下:
double tan = Math.tan(Math.PI);
System.out.println("tan = " + tan);
Math.asin()
Math.asin()方法计算-1到1之间值的反正弦值。示例如下:
double asin = Math.asin(1.0);
System.out.println("asin = " + asin);
Math.acos()
Math.acos()方法计算-1和1之间值的反余弦值。示例如下:
double acos = Math.acos(1.0);
System.out.println("acos = " + acos);
Math.atan()
Math.atan()方法计算介于-1和1之间值的反正切。示例如下:
double atan = Math.atan(1.0);
System.out.println("atan = " + atan);
Math.atan2()
我不完全确定Math.atan2()方法在数学上是什么。这是JavaDoc所说的:
“从 x 轴到点 (x,y) 之间的角度。”。
如果你需要这个方法,请阅读JavaDoc,但现在你至少知道它存在。
Math.sinh()
Math.sinh()方法计算-1和1之间值的双曲正弦值。示例如下:
double sinh = Math.sinh(1.0);
System.out.println("sinh = " + sinh);
Math.cosh()
Math.cosh()方法计算介于-1和1之间值的双曲余弦值。示例如下:
double cosh = Math.cosh(1.0);
System.out.println("cosh = " + cosh);
Math.tanh()
Math.tanh()方法计算介于-1和1之间值的双曲线切线值。示例如下:
double tanh = Math.tanh(1.0);
System.out.println("tanh = " + tanh);
Math.toDegrees()
Math.toDegrees()方法将弧度转换为度数。示例如下:
double degrees = Math.toDegrees(Math.PI);
System.out.println("degrees = " + degrees);
Math.toRadians()
Math.toRadians()方法将角度转换为弧度。示例如下:
double radians = Math.toRadians(180);
System.out.println("radians = " + radians);
下一篇: Java数组