Bitwise Operators 位運(yùn)算符

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.

在對(duì)整數(shù)類(lèi)型進(jìn)行處理的時(shí),還有能夠直接處理構(gòu)成整數(shù)的各個(gè)位的運(yùn)算符。這意味著你可以使用掩碼技術(shù)來(lái)處理一個(gè)數(shù)字中的各個(gè)獨(dú)立位。這些位運(yùn)算符是:

& ("與") | ("或") ^ ("異或") ~ ("非")

這些運(yùn)算符工作在比特形式下。例如,如果n是一個(gè)整型變量,那么

int fourthBitFromRight = (n & 8) / 8;

這條語(yǔ)句將在n的二進(jìn)制表示從右起第四位是1時(shí)得出結(jié)果1,否則為0。使用&符號(hào)搭配適當(dāng)?shù)?的指數(shù)冪可以使你屏蔽某一個(gè)位以外的所有位。

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.

當(dāng)應(yīng)用于布爾值時(shí),&和|運(yùn)算將產(chǎn)生一個(gè)布爾值。這些運(yùn)算符和&&以及||運(yùn)算符是類(lèi)似的,但是&和|并不以短路形式運(yùn)算。也就是說(shuō),兩個(gè)參數(shù)在結(jié)果算出之前就參與運(yùn)算。(譯者注,參見(jiàn)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.

還有>>和<<運(yùn)算符,可以向左或者向右移動(dòng)一位。這些運(yùn)算符在你需要通過(guò)位模式來(lái)執(zhí)行按位掩碼時(shí)是非常方便的,例如:

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

最后,>>>運(yùn)算符用0填寫(xiě)頭兩位,而>>把符號(hào)為增加到頭一位。沒(méi)有<<<運(yùn)算符。

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.

移位運(yùn)算符右邊的參數(shù)被減少到32(除非左邊的參數(shù)較長(zhǎng),這種情況下,右邊的較少到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++中,并不保證>>進(jìn)行的是算術(shù)移位(擴(kuò)展符號(hào)位)還是邏輯移位(以0填充)。設(shè)備可以在二者中選擇更有效的操作。這就意味著C/C++中的>>運(yùn)算符的確僅僅是為非負(fù)數(shù)定義的。Java去除了這種歧義性。

Mathematical Functions and Constants 數(shù)學(xué)函數(shù)與常量

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類(lèi)包含一組你有時(shí)會(huì)用到的數(shù)學(xué)函數(shù),這取決于你所編程序的類(lèi)型。要計(jì)算一個(gè)數(shù)字的平方根,需要使用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方法有一個(gè)微妙的差別。println方法對(duì)一個(gè)對(duì)象進(jìn)行操作,即System類(lèi)中定義的System.out。但是Math類(lèi)中的sqrt方法并不對(duì)任何對(duì)象進(jìn)行操作。這樣的方法稱(chēng)作靜態(tài)方法。你可在第四章中學(xué)習(xí)更多有關(guān)靜態(tài)方法的知識(shí)。

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語(yǔ)言沒(méi)有指數(shù)冪運(yùn)算符,你需要使用Math類(lèi)中的pow方法。語(yǔ)句

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

將y的值設(shè)置為x的a次冪。pow方法的兩個(gè)參數(shù)都應(yīng)該是double類(lèi)型,且返回值也是double類(lèi)型。

The Math class supplies the usual trigonometric functions

Math類(lèi)提供了常用的三角函數(shù):

Math.sin

Math.cos

Math.tan

Math.atan

Math.atan2

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

以及指數(shù)函數(shù)及其逆運(yùn)算——自然對(duì)數(shù):

Math.exp

Math.log

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

最后,介紹兩個(gè)與數(shù)學(xué)常量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開(kāi)始,你可以在源文件起始處使用如下代碼來(lái)避免每次使用數(shù)學(xué)方法和常量的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.

我們將在第四章討論靜態(tài)導(dǎo)入。

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類(lèi)中的函數(shù)使用計(jì)算機(jī)浮點(diǎn)運(yùn)算單元中的例程。如果可預(yù)測(cè)的結(jié)果完全重于快速表現(xiàn),則使用StrictMath類(lèi)。這個(gè)類(lèi)從“自由分布數(shù)學(xué)庫(kù)”中實(shí)現(xiàn)運(yùn)算,保證各個(gè)平臺(tái)上的統(tǒng)一的結(jié)果。算法源碼參見(jiàn)http://www.netlib.org/fdlibm/index.html。不論何時(shí)fdlibm提供對(duì)一個(gè)函數(shù)的多種定義,StrictMath類(lèi)始終遵循以“e”開(kāi)始命名的IEEE 754版本。

Conversions Between Numeric Types 數(shù)字類(lèi)型之間的轉(zhuǎn)換

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

在多種數(shù)字類(lèi)型之間進(jìn)行轉(zhuǎn)換是常有的事,圖3-1說(shuō)明了合法的轉(zhuǎn)換:

3-1 數(shù)字類(lèi)型之間的合法轉(zhuǎn)換

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中的六個(gè)實(shí)箭頭表示無(wú)信息丟失的轉(zhuǎn)換。三個(gè)虛箭頭表示可能丟失精度的轉(zhuǎn)換。例如,一個(gè)大的整型數(shù)字,如123456789,其位數(shù)多于浮點(diǎn)型能夠表示的位數(shù)。當(dāng)這個(gè)整型數(shù)轉(zhuǎn)換成浮點(diǎn)型時(shí),結(jié)果值仍然很大,但是丟失了精度。

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.

當(dāng)兩個(gè)數(shù)字和一個(gè)二進(jìn)制運(yùn)算符結(jié)合在一起(例如n+f中,n是一個(gè)整數(shù),而f是一個(gè)浮點(diǎn)數(shù)),兩個(gè)操作數(shù)都會(huì)在運(yùn)算之前被轉(zhuǎn)換為通用類(lèi)型。

  • 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.
  • 如果兩個(gè)操作數(shù)有一個(gè)是double型,另一個(gè)轉(zhuǎn)換為double型。
  • 否則,如果兩個(gè)操作數(shù)有一個(gè)為float型,則另一個(gè)轉(zhuǎn)換為float型。
  • 否則,如果兩個(gè)操作數(shù)有一個(gè)為long型,則另一個(gè)轉(zhuǎn)換為long型。
  • 否則,兩個(gè)操作數(shù)都被轉(zhuǎn)換為整型。

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:

在前面的章節(jié)中,你可以看到整型值在需要的時(shí)候可以自動(dòng)轉(zhuǎn)換為double型,另一方面,有時(shí)你也希望把double型轉(zhuǎn)換為整型。在Java中,數(shù)字類(lèi)型的轉(zhuǎn)換是允許的,但是丟失信息也是自然的。丟失信息的轉(zhuǎn)換是依靠強(qiáng)制轉(zhuǎn)換來(lái)完成的。強(qiáng)制轉(zhuǎn)換的語(yǔ)句是在變量名前加上由圓括號(hào)括起來(lái)的目標(biāo)類(lèi)型,例如:

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,因?yàn)楦↑c(diǎn)型向整型的強(qiáng)制轉(zhuǎn)換舍棄了小數(shù)部分。

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:

如果你想把一個(gè)浮點(diǎn)數(shù)四舍五入成最接近的整數(shù)(在大多數(shù)情況下,這是更有用的操作),使用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.

現(xiàn)在,變量nx的值就是10了。在你調(diào)用round方法時(shí),你還是需要進(jìn)行強(qiáng)制轉(zhuǎn)換(int)。原因是round方法的返回值類(lèi)型是long,而long類(lèi)型在給int變量賦值時(shí),由于可能產(chǎn)生信息丟失,所以必須采用顯式轉(zhuǎn)換。

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.

如果你試圖將某種類(lèi)型的數(shù)字轉(zhuǎn)換為比原類(lèi)型范圍小的目標(biāo)類(lèi)型,結(jié)果將被截?cái)啵a(chǎn)生一個(gè)不同的值,例如(byte) 300 的結(jié)果實(shí)際上是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.

你不能在布爾型和數(shù)字類(lèi)型之間進(jìn)行轉(zhuǎn)換。這種轉(zhuǎn)換將產(chǎn)生常見(jiàn)錯(cuò)誤。極少數(shù)情況下,你希望將布爾值轉(zhuǎn)換為一個(gè)數(shù)字,此時(shí)你可以使用條件表達(dá)式,例如b?1:0

Parentheses and Operator Hierarchy 圓括號(hào)和運(yùn)算優(yōu)先級(jí)

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展示了運(yùn)算符的優(yōu)先級(jí)。如果沒(méi)有使用括號(hào),運(yùn)算符將按照表中顯示的優(yōu)先級(jí)進(jìn)行運(yùn)算。除了表中指明的右結(jié)合的運(yùn)算符,同一級(jí)別的運(yùn)算符自左向右運(yùn)算。例如,&&和優(yōu)先級(jí)高于||,表達(dá)式

a && b || c

means等于

(a && b) || c

Because += associates right to left, the expression

由于+=自右向左結(jié)合,表達(dá)式

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沒(méi)有逗號(hào)運(yùn)算符,但是你可以在一個(gè)for語(yǔ)句中的第一個(gè)和第三個(gè)位置使用一個(gè)逗號(hào)分隔的表達(dá)式。

C語(yǔ)言中的逗號(hào)運(yùn)算符:

C語(yǔ)言中逗號(hào)“,”也是一種運(yùn)算符,稱(chēng)為逗號(hào)運(yùn)算符。 其功能是把兩個(gè)表達(dá)式連接起來(lái)組成一個(gè)表達(dá)式, 稱(chēng)為逗號(hào)表達(dá)式。
其一般形式為: 表達(dá)式1,表達(dá)式2 其求值過(guò)程是分別求兩個(gè)表達(dá)式的值,并以表達(dá)式2的值作為整個(gè)逗號(hào)表達(dá)式的值。
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等于整個(gè)逗號(hào)表達(dá)式的值,也就是表達(dá)式2的值,x是第一個(gè)表達(dá)式的值。對(duì)于逗號(hào)表達(dá)式還要說(shuō)明幾點(diǎn):
1.逗號(hào)表達(dá)式一般形式中的表達(dá)式1和表達(dá)式2 也可以又是逗號(hào)表達(dá)式。例如: 表達(dá)式1,(表達(dá)式2,表達(dá)式3) 形成了嵌套情形。因此可以把逗號(hào)表達(dá)式擴(kuò)展為以下形式: 表達(dá)式1,表達(dá)式2,…表達(dá)式n 整個(gè)逗號(hào)表達(dá)式的值等于表達(dá)式n的值。
2.程序中使用逗號(hào)表達(dá)式,通常是要分別求逗號(hào)表達(dá)式內(nèi)各表達(dá)式的值,并不一定要求整個(gè)逗號(hào)表達(dá)式的值。
3.并不是在所有出現(xiàn)逗號(hào)的地方都組成逗號(hào)表達(dá)式,如在變量說(shuō)明中,函數(shù)參數(shù)表中逗號(hào)只是用作各變量之間的間隔符。
以上是摘抄來(lái)的 我本人覺(jué)得自己最常使用逗號(hào)運(yùn)算符是在
for循環(huán)里
for (i = 0, j = 0; i < 3 && j < 3; i++, j+=2) {
printf("i = %d, j = %d",i,j);
}

Enumerated Types 枚舉類(lèi)型

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).

有時(shí)候,一個(gè)變量需要僅保存一組有限值的集合。例如,你可能出售四種尺寸的衣服或者匹薩:小號(hào)、中號(hào)、大號(hào)和特大號(hào)。當(dāng)然,你可以給這四種型號(hào)編號(hào)為1,2,3,4或者S,M,L,X。但這是一個(gè)具有錯(cuò)誤傾向的設(shè)置。變量很可能會(huì)承載一個(gè)錯(cuò)誤的值(比如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開(kāi)始,你可以在遇到這種情況時(shí)定義自己的枚舉類(lèi)型。一個(gè)枚舉類(lèi)型具有有限個(gè)數(shù)的命名變量。例如:

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

Now you can declare variables of this type:

現(xiàn)在,你可以定義這種類(lèi)型的變量:

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.

一個(gè)Size類(lèi)型的變量只能承載Size類(lèi)型中聲明的一個(gè)值,或者承載一個(gè)特殊值null來(lái)表示這個(gè)變量沒(méi)有被設(shè)置任何值。

We discuss enumerated types in greater detail in Chapter 5.

我們將在第五章更詳細(xì)的討論枚舉類(lèi)型。


文章來(lái)源:http://x-spirit.spaces.live.com/Blog/cns!CC0B04AE126337C0!314.entry