Bitwise Operators 位运算符

When working with any of the integer types, you have operators that can work directly with the bits that make up the integers. This means that you can use masking techniques to get at individual bits in a number. The bitwise operators are

& ("and") | ("or") ^ ("xor") ~ ("not")

These operators work on bit patterns. For example, if n is an integer variable, then

int fourthBitFromRight = (n & 8) / 8;

gives you a 1 if the fourth bit from the right in the binary representation of n is 1, and 0 if not. Using & with the appropriate power of 2 lets you mask out all but a single bit.

在对整数类型进行处理的时,还有能够直接处理构成整数的各个位的运算符。这意味着你可以使用掩码技术来处理一个数字中的各个独立位。这些位运算符是:

& ("与") | ("或") ^ ("异或") ~ ("非")

这些运算符工作在比特形式下。例如,如果n是一个整型变量,那么

int fourthBitFromRight = (n & 8) / 8;

这条语句将在n的二进制表示从右起第四位是1时得出结果1,否则为0。使用&符号搭配适当的2的指数幂可以使你屏蔽某一个位以外的所有位。

NOTE 注释

 

When applied to boolean values, the & and | operators yield a boolean value. These operators are similar to the && and || operators, except that the & and | operators are not evaluated in "short circuit" fashion. That is, both arguments are first evaluated before the result is computed.

当应用于布尔值时,&和|运算将产生一个布尔值。这些运算符和&&以及||运算符是类似的,但是&和|并不以短路形式运算。也就是说,两个参数在结果算出之前就参与运算。(译者注,参见http://www.itsway.net/java/java020505.aspx

There are also >> and << operators, which shift a bit pattern to the right or left. These operators are often convenient when you need to build up bit patterns to do bit masking:

int fourthBitFromRight = (n & (1 << 3)) >> 3;

Finally, a >>> operator fills the top bits with zero, whereas >> extends the sign bit into the top bits. There is no <<< operator.

还有>>和<<运算符,可以向左或者向右移动一位。这些运算符在你需要通过位模式来执行按位掩码时是非常方便的,例如:

int fourthBitFromRight = (n & (1 << 3)) >> 3;

最后,>>>运算符用0填写头两位,而>>把符号为增加到头一位。没有<<<运算符。

CAUTION 注意

 

The right-hand side argument of the shift operators is reduced modulo 32 (unless the left-hand side is a long, in which case the right-hand side is reduced modulo 64). For example, the value of 1 << 35 is the same as 1 << 3 or 8.

移位运算符右边的参数被减少到32(除非左边的参数较长,这种情况下,右边的较少到64)。例如,1<<35的值和1<<3或者1<<8是一样的。

C++ NOTE C++注释

 

In C/C++, there is no guarantee as to whether >> performs an arithmetic shift (extending the sign bit) or a logical shift (filling in with zeroes). Implementors are free to choose whatever is more efficient. That means the C/C++ >> operator is really only defined for non-negative numbers. Java removes that ambiguity.

在C/C++中,并不保证>>进行的是算术移位(扩展符号位)还是逻辑移位(以0填充)。设备可以在二者中选择更有效的操作。这就意味着C/C++中的>>运算符的确仅仅是为非负数定义的。Java去除了这种歧义性。

Mathematical Functions and Constants 数学函数与常量

The Math class contains an assortment of mathematical functions that you may occasionally need, depending on the kind of programming that you do.

To take the square root of a number, you use the sqrt method:

Math类包含一组你有时会用到的数学函数,这取决于你所编程序的类型。要计算一个数字的平方根,需要使用sqrt方法:

double x = 4;

double y = Math.sqrt(x);

System.out.println(y); // 打印 2.0

NOTE 注释

 

There is a subtle difference between the println method and the sqrt method. The println method operates on an object, System.out, defined in the System class. But the sqrt method in the Math class does not operate on any object. Such a method is called a static method. You can learn more about static methods in Chapter 4.

println方法和sqrt方法有一个微妙的差别。println方法对一个对象进行操作,即System类中定义的System.out。但是Math类中的sqrt方法并不对任何对象进行操作。这样的方法称作静态方法。你可在第四章中学习更多有关静态方法的知识。

The Java programming language has no operator for raising a quantity to a power: you must use the pow method in the Math class. The statement

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

sets y to be x raised to the power a (xa). The pow method has parameters that are both of type double, and it returns a double as well.

Java语言没有指数幂运算符,你需要使用Math类中的pow方法。语句

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

将y的值设置为x的a次幂。pow方法的两个参数都应该是double类型,且返回值也是double类型。

The Math class supplies the usual trigonometric functions

Math类提供了常用的三角函数:

Math.sin

Math.cos

Math.tan

Math.atan

Math.atan2

and the exponential function and its inverse, the natural log:

以及指数函数及其逆运算——自然对数:

Math.exp

Math.log

Finally, two constants denote the closest possible approximations to the mathematical constants p and e:

最后,介绍两个与数学常量p 和 e的值非常近似的常量:

Math.PI

Math.E

TIP提示

 

Starting with JDK 5.0, you can avoid the Math prefix for the mathematical methods and constants by adding the following line to the top of your source file:

从JDK5.0开始,你可以在源文件起始处使用如下代码来避免每次使用数学方法和常量的Math前缀。

import static java.lang.Math.*;

For example,

例如:

System.out.println("The square root of \u03C0 is " + sqrt(PI));

We discuss static imports in Chapter 4.

我们将在第四章讨论静态导入。

NOTE注意

 

The functions in the Math class use the routines in the computer's floating-point unit for fastest performance. If completely predictable results are more important than fast performance, use the StrictMath class instead. It implements the algorithms from the "Freely Distributable Math Library" fdlibm, guaranteeing identical results on all platforms. See http://www.netlib.org/fdlibm/index.html for the source of these algorithms. (Whenever fdlibm provides more than one definition for a function, the StrictMath class follows the IEEE 754 version whose name starts with an "e".)

为了获得最快的性能,Math类中的函数使用计算机浮点运算单元中的例程。如果可预测的结果完全重于快速表现,则使用StrictMath类。这个类从“自由分布数学库”中实现运算,保证各个平台上的统一的结果。算法源码参见http://www.netlib.org/fdlibm/index.html。不论何时fdlibm提供对一个函数的多种定义,StrictMath类始终遵循以“e”开始命名的IEEE 754版本。

Conversions Between Numeric Types 数字类型之间的转换

It is often necessary to convert from one numeric type to another. Figure 3-1 shows the legal conversions.

在多种数字类型之间进行转换是常有的事,图3-1说明了合法的转换:

3-1 数字类型之间的合法转换

The six solid arrows in Figure 3-1 denote conversions without information loss. The three dotted arrows denote conversions that may lose precision. For example, a large integer such as 123456789 has more digits than the float type can represent. When the integer is converted to a float, the resulting value has the correct magnitude but it loses some precision.

图3-1中的六个实箭头表示无信息丢失的转换。三个虚箭头表示可能丢失精度的转换。例如,一个大的整型数字,如123456789,其位数多于浮点型能够表示的位数。当这个整型数转换成浮点型时,结果值仍然很大,但是丢失了精度。

int n = 123456789;

float f = n; // f is 1.23456792E8

When two values with a binary operator (such as n + f where n is an integer and f is a floating-point value) are combined, both operands are converted to a common type before the operation is carried out.

当两个数字和一个二进制运算符结合在一起(例如n+f中,n是一个整数,而f是一个浮点数),两个操作数都会在运算之前被转换为通用类型。

  • If either of the operands is of type double, the other one will be converted to a double.
  • Otherwise, if either of the operands is of type float, the other one will be converted to a float.
  • Otherwise, if either of the operands is of type long, the other one will be converted to a long.
  • Otherwise, both operands will be converted to an int.
  • 如果两个操作数有一个是double型,另一个转换为double型。
  • 否则,如果两个操作数有一个为float型,则另一个转换为float型。
  • 否则,如果两个操作数有一个为long型,则另一个转换为long型。
  • 否则,两个操作数都被转换为整型。

Casts

In the preceding section, you saw that int values are automatically converted to double values when necessary. On the other hand, there are obviously times when you want to consider a double as an integer. Numeric conversions are possible in Java, but of course information may be lost. Conversions in which loss of information is possible are done by means of casts. The syntax for casting is to give the target type in parentheses, followed by the variable name. For example:

在前面的章节中,你可以看到整型值在需要的时候可以自动转换为double型,另一方面,有时你也希望把double型转换为整型。在Java中,数字类型的转换是允许的,但是丢失信息也是自然的。丢失信息的转换是依靠强制转换来完成的。强制转换的语句是在变量名前加上由圆括号括起来的目标类型,例如:

double x = 9.997;

int nx = (int) x;

Then, the variable nx has the value 9 because casting a floating-point value to an integer discards the fractional part.

这样,变量nx的值就是0,因为浮点型向整型的强制转换舍弃了小数部分。

If you want to round a floating-point number to the nearest integer (which is the more useful operation in most cases), use the Math.round method:

如果你想把一个浮点数四舍五入成最接近的整数(在大多数情况下,这是更有用的操作),使用Math.round方法:

double x = 9.997;

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

Now the variable nx has the value 10. You still need to use the cast (int) when you call round. The reason is that the return value of the round method is a long, and a long can only be assigned to an int with an explicit cast because there is the possibility of information loss.

现在,变量nx的值就是10了。在你调用round方法时,你还是需要进行强制转换(int)。原因是round方法的返回值类型是long,而long类型在给int变量赋值时,由于可能产生信息丢失,所以必须采用显式转换。

CAUTION注意

If you try to cast a number of one type to another that is out of the range for the target type, the result will be a truncated number that has a different value. For example, (byte) 300 is actually 44.

如果你试图将某种类型的数字转换为比原类型范围小的目标类型,结果将被截断,产生一个不同的值,例如(byte) 300 的结果实际上是44。

C++ NOTE C++注释

You cannot cast between boolean values and any numeric type. This convention prevents common errors. In the rare case that you want to convert a boolean value to a number, you can use a conditional expression such as b ? 1 : 0.

你不能在布尔型和数字类型之间进行转换。这种转换将产生常见错误。极少数情况下,你希望将布尔值转换为一个数字,此时你可以使用条件表达式,例如b?1:0

Parentheses and Operator Hierarchy 圆括号和运算优先级

Table 3-4 shows the precedence of operators. If no parentheses are used, operations are performed in the hierarchical order indicated. Operators on the same level are processed from left to right, except for those that are right associative, as indicated in the table. For example, because && has a higher precedence than ||, the expression

Table 3-4. Operator Precedence

Operators

Associativity

[] . () (method call)

Left to right

! ~ ++ -- + (unary) – (unary) () (cast) new

Right to left

* / %

Left to right

+ -

Left to right

<< >> >>>

Left to right

< <= > >= instanceof

Left to right

== !=

Left to right

&

Left to right

^

Left to right

|

Left to right

&&

Left to right

||

Left to right

?:

Right to left

= += -= *= /= %= &= |= ^= <<= >>= >>>=

Right to left

表3-4展示了运算符的优先级。如果没有使用括号,运算符将按照表中显示的优先级进行运算。除了表中指明的右结合的运算符,同一级别的运算符自左向右运算。例如,&&和优先级高于||,表达式

a && b || c

means等于

(a && b) || c

Because += associates right to left, the expression

由于+=自右向左结合,表达式

a += b += c

means等于

a += (b += c)

That is, the value of b += c (which is the value of b after the addition) is added to a.

也就是b+=c的值(即第一次加法后b的值)再加到a上。

C++ NOTE C++注释

Unlike C or C++, Java does not have a comma operator. However, you can use a comma-separated list of expressions in the first and third slot of a for statement.

与C或C++不同,Java没有逗号运算符,但是你可以在一个for语句中的第一个和第三个位置使用一个逗号分隔的表达式。

C语言中的逗号运算符:

C语言中逗号“,”也是一种运算符,称为逗号运算符。 其功能是把两个表达式连接起来组成一个表达式, 称为逗号表达式。
其一般形式为: 表达式1,表达式2 其求值过程是分别求两个表达式的值,并以表达式2的值作为整个逗号表达式的值。
void main(){
int a=2,b=4,c=6,x,y;
y=(x=a+b),(b+c);
printf("y=%d,x=%d",y,x);
}
a<--2,b<--4,c<--6,x<--0,y<--0
x<--a+b,y<---b+c
本例中,y等于整个逗号表达式的值,也就是表达式2的值,x是第一个表达式的值。对于逗号表达式还要说明几点:
1.逗号表达式一般形式中的表达式1和表达式2 也可以又是逗号表达式。例如: 表达式1,(表达式2,表达式3) 形成了嵌套情形。因此可以把逗号表达式扩展为以下形式: 表达式1,表达式2,…表达式n 整个逗号表达式的值等于表达式n的值。
2.程序中使用逗号表达式,通常是要分别求逗号表达式内各表达式的值,并不一定要求整个逗号表达式的值。
3.并不是在所有出现逗号的地方都组成逗号表达式,如在变量说明中,函数参数表中逗号只是用作各变量之间的间隔符。
以上是摘抄来的 我本人觉得自己最常使用逗号运算符是在
for循环里
for (i = 0, j = 0; i < 3 && j < 3; i++, j+=2) {
printf("i = %d, j = %d",i,j);
}

Enumerated Types 枚举类型

Sometimes, a variable should only hold a restricted set of values. For example, you may sell clothes or pizza in four sizes: small, medium, large, and extra large. Of course, you could encode these sizes as integers 1, 2, 3, 4, or characters S, M, L, and X. But that is an error-prone setup. It is too easy for a variable to hold a wrong value (such as 0 or m).

有时候,一个变量需要仅保存一组有限值的集合。例如,你可能出售四种尺寸的衣服或者匹萨:小号、中号、大号和特大号。当然,你可以给这四种型号编号为1,2,3,4或者S,M,L,X。但这是一个具有错误倾向的设置。变量很可能会承载一个错误的值(比如0或者m)。

Starting with JDK 5.0, you can define your own enumerated type whenever such a situation arises. An enumerated type has a finite number of named values. For example,

从JDK5.0开始,你可以在遇到这种情况时定义自己的枚举类型。一个枚举类型具有有限个数的命名变量。例如:

enum Size { SMALL, MEDIUM, LARGE, EXTRA_LARGE };

Now you can declare variables of this type:

现在,你可以定义这种类型的变量:

Size s = Size.MEDIUM;

A variable of type Size can hold only one of the values listed in the type declaration or the special value null that indicates that the variable is not set to any value at all.

一个Size类型的变量只能承载Size类型中声明的一个值,或者承载一个特殊值null来表示这个变量没有被设置任何值。

We discuss enumerated types in greater detail in Chapter 5.

我们将在第五章更详细的讨论枚举类型。


文章来源:http://x-spirit.spaces.live.com/Blog/cns!CC0B04AE126337C0!314.entry