"Java Puzzles" Java's little knowledge of anti-common sense

Source: Internet
Author: User


First,  Q: please for i = = i + 1; provide a declaration to make the condition valid.


Analysis: a number never equals 1 of its own, right? What if the number is infinitely large? Java enforces the use of IEEE binary floating-point arithmetic standard IEEE 754, which allows you to represent infinity with a double or float. Infinity plus 1 is infinitely large. If I is declared as infinity then i = = i + 1 is established.


A: You can declare I with any floating-point arithmetic expression that is computed as infinity, for example double i = 1.0/0.0; However, it is best to use the constant double i = double.positive_infinity provided by the standard class library;

Summary: In fact, it is not necessary to declare I as infinity can also make the conditions, any large enough floating point number can achieve this purpose. For example double i = 1.0e40; This can be useful because the larger the floating-point value, the greater the interval between it and its subsequent values. This distribution of floating-point numbers is an inevitable result of using a fixed number of significant bits to represent them. Adding 1 to a floating-point number that is large enough does not change its value because 1 is not sufficient to "fill the gap between it and its successor". A floating-point operation returns a floating-point value closest to its exact mathematical result. Once the distance between adjacent floating-point values is greater than 2, then adding 1 to one of the floating-point values will have no effect because the result does not reach half of the two values. The minimum progression for float type plus 1 does not produce any effect is 2^25, or 33,554,432, whereas for double type the minimum series is 2^54, which is approximately 1.8* 10^16. The distance between adjacent floating-point numbers is called a ULP, which is the acronym for the "smallest unit in the last place". In the 5. The Math.ulp method was introduced in version 0 to calculate the ulp of a float or double value.

In short, it is possible to use a double or a float value to denote infinity. Most people will be a bit surprised when they first hear this, probably because we can't use any integer type to represent the cause of infinity.

2nd, when you add a small floating-point number to a large float, it will not change the value of the large floating-point numbers. It's too counterintuitive, because it's not true for actual numbers. We should remember that binary floating-point arithmetic is just an approximation of the actual arithmetic.


Second, Q: Please provide a statement for i!=i so that conditions are established.


Analysis: A number is always equal to its own, right?! However, IEEE 754 floating-point arithmetic retains a special value that represents a number that is not a number, and this value is NaN ("Not a number is an abbreviation of not a digit"). for all floating-point calculations that do not have a good numeric definition, for example, 0.0/0.0 its value is it. The specification describes a NaN that is not equal to any floating-point value including itself. so if I was initialized to Nan then i! = I was set up.

A: I can be initialized with any floating-point arithmetic expression that evaluates to NaN, such as double i = 0.0/0.0; Also in order to express clarity you can use the constant supplied by the standard class library double i = Double.NaN;


Summary: There are other amazing places to NaN. any floating-point operation as long as one or more of its operands is Nan, the result is Nan. This rule is very reasonable, but it has a strange result. For example, the following program will print false:

Class Test {public static void main (string[] args) {double i = 0.0/0.0; System.out.println (I-i = = 0); }}

This rule of Nan is based on the principle that once a computation has produced a Nan, it is corrupted and no further calculations can be made to repair such damage. the NaN value intentionally causes the damaged calculation to continue until it is convenient to handle the situation.

in short, both the float and double types have a special NaN value that represents the number that is not a number. The rules for calculations involving NaN values are simple and sensible, but the results of these rules can be counterintuitive.


Third, Q: please for i!=1+0; Provide a declaration to make the condition valid. But you can't use floating-point numbers like you did on the topic.


Analysis: as in the previous question, this puzzle seems to be impossible at first. After all, a number is always equal to itself plus 0, you are forbidden to use floating-point numbers, so NaN cannot be used. There is no equivalent of NaN in the integer type. We can certainly conclude that the type of I must be a non-numeric type and that there is a solution to the puzzle. The only non-numeric type that is defined on the + operator is String. The + operator is overloaded, and for the string type it does not add but string connections. If an operand in the connection has a non-string type, the operand is converted to a string before the connection.


A: In fact I can be initialized to any value, as long as it is of type String. For example String i= "Search public number Ape_it";


Summary: operator overloading is easily misleading. The plus sign in this puzzle appears to represent an addition, but by selecting the appropriate type for the variable i is string we have it perform a string join operation. Even because the variable is named I makes the subject more misleading because I is usually reserved as an integer variable name. Good variable names, method names, and class names are at least as important as good annotations for the readability of the program.


Four, Q: please provide a declaration of I that transforms the following loop into an infinite loop:

while (i! = 0) {i >>>= 1;}

Analysis: >>>= is an assignment operator that corresponds to an unsigned right-shift operator. 0 is moved from left to the position vacated by the shift operation, even if the negative number is shifted.

for the shift to be valid, I must be an integer of type Byte, char, short, int, or long. The unsigned Right shift operator moves 0 from the left. As a result, it appears that the loop performs iterations as many times as the largest integer type occupies 64 times. How can it be turned into an infinite loop? The key to solving this puzzle is that>>>= is a compound assignment operator. Compound assignment operators include *=,/=,%=, + =,-=, <<=, >>=, >>>=, &=, ^=, and | = An unfortunate fact about mixed operators is that they may automatically perform a narrowing of the original type conversion. This conversion converts a number type into another type that lacks the ability to represent. Narrowing the original type conversion may lose information about the progression or the precision of the numeric value.


A: Suppose you put the following declaration in front of the loopShort i =-1;Since the initial value of I (short) 0xFFFF is non-0, the loop experience is performed. When performing a shift operation, the first step is to promote I to the int type.all arithmetic operations perform such an increase on the operands of the short, byte, and char types. This promotion is a widening of the original type conversion, so no information is lost. This promotion performs a symbol extension, so the resulting int value is 0xFFFFFFFF. The value then shifts 1 bits to the right, but does not use the symbol extension, resulting in an int numeric 0x7fffffff. The last value is stored back in I. To put an int value into a short variable, Java executes the dreaded narrowing primitive type conversion, which truncates the high 16 bits directly. This leaves only (short) 0xffff, and we are back at the beginning. The second and subsequent iterations of the loop are the same, so the loop will never terminate.


Summary: This behavior also occurs if you declare I as a short or byte variable and initialize to any negative number. If you declare I to be a char, then you will not be able to get an infinite loop because char is unsigned, so widening the original type conversion before the shift does not execute the symbol extension. Anywaydo not use compound assignment operators on top of variables of type short, Byte, or char. Because such an expression performs a mixed-type arithmetic operation, it can easily cause confusion. Worse, their execution will implicitly transform the narrowing of information that is lost, and the result is catastrophic.


Five, Q: please for I <= J && J <= I && i! = j ; provide a declaration to make the condition valid.

Analysis: If I <= J and J <= I,i is not certainly equal to J? This property is definitely valid for real numbers. In fact, it is so important that it has such a definition: the <= relationship on the real number is against the claim. Java's <= operator was objected to before version 5.0, but it was no longer after the 5.0 version.

prior to version 5.0, the Java numeric comparison operators (<, <=, >, and >=) required their two operands to be of the original numeric type (byte, char, short, int, long, float, and double). However, in version 5.0, the specification was modified and the new specification describes that the type of each operand must be convertible to the original numeric type.

In version 5.0, automatic packaging (auto-boxing) and auto-wrapping (auto-unboxing) were added to the Java language. The <= operator is still objectionable on the original set of numeric types, but it is now applied to the wrapped number type. (The number types that are wrapped are: Byte, Character, short, Integer, Long, Float, and Double.) The <= operator is not objected to on these types of operands, because the Java sentencing operator (= = and! =) performs a reference comparison rather than a comparison of values when acting on an object reference.


A: The following declaration gives the expression (i <= J && J <= I && i! = j) A value of true:

Integer i = new Integer (0), Integer j = new Integer (0);

The first two sub-expressions (I <= J and J <= i) perform the unpacking conversion on I and J, and compare the resulting int values in numbers. Both I and J represent 0, so these two sub-expressions are evaluated as true. The third subexpression (i! = j) Performs an identity comparison on object references I and J, because they are initialized to a new Integer instance, so the third subexpression is also evaluated as true.

Summary: There is a fundamental difference between the behavior of the numeric comparison operator and the operator of the sentence when the two operands are of the wrapped number: The numeric comparison operator performs a value comparison, and the operator performs a comparison of the reference identity.



note: This "Java Confusion" series are bloggers reading "Java doubts" The original book after the interpretation of the original book and examples of the adaptation and then write a post to publish. All examples are personally tested and shared on GitHub. Use these examples to motivate yourself to benefit others. At the same time, all the posts in this series will be published in the blogger personal public search "Love Ape" or "ape_it" to facilitate reading. If there is any infringement of the original rights of the author, please inform the blogger in time to delete if the reader has objections to the content of the text or questions are welcome through the blog post or public messages and other ways to discuss together.

Source code Address Https://github.com/rocwinger/java-disabuse


This article from "Winger" blog, declined reprint!

"Java Puzzles" Java's little knowledge of anti-common sense

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.