Brought to you by EarthWeb
ITKnowledge Logo Login Graphic Click Here!
Click Here!
ITKnowledge
Find:
 
EXPERT SEARCH ----- nav

EarthWeb Direct

EarthWeb sites: other sites

Previous Table of Contents Next


The mechanics of conversion

Now that we’ve seen when conversions may take place, let’s investigate how. Some conversions, such as an int to a long, are easy and never lose information. Others, such as a long to an int, are trickier because not all longs have int equivalents. For example, suppose that a byte variable b holds the value 92. In binary notation, this is 01011100. Because an int needs 32 bits, three extra zero bytes are added to the front of b, making it 000000000000-00000000000001011100.

Now suppose instead that the value of b is -92. Using two’s complement arithmetic, we see that the binary expansion of -92 is 10100011 + 00000001 = 10100100. Now if you just attach three bytes of zeroes on the left side of this number, you get 00000000000000000000000010100100, which is not -92 (since the sign bit is zero, the number must be positive) but rather 164, not the same thing at all. In fact, it’s not even off by a sign. If that were the problem, it would be simple enough to change the leftmost bit to 1. However, here that gives you -164, which isn’t -92 any more than 164 is.

On the other hand, look what happens if you extend -92 with three bytes full of ones. You get 11111111111111111111111110100100. This is obviously a negative number since the leftmost bit is one. Using two’s complement arithmetic to find out which number it is, you invert the number and add one:

             00000000000000000000000001011011
            +00000000000000000000000000000001
             00000000000000000000000001011100

which, lo and behold, is 92! Thus, the proper way to convert an integer type to a wider format is sign extension. That is, take whatever bit is in the sign bit and add as many extra bytes as you need filled with that bit. This works for other widening casts between integer types as well. For example, to change a positive int to the equivalent long, just add four bytes of zeroes to the front. To change a negative int to the equivalent long just attach four more bytes of ones to the front of the int. Performed in this fashion, widening integer casts — that is, casts that go from a smaller type to a larger type — never lose information.

The same cannot be said for narrowing casts. A narrowing cast moves from a wider type, like int, to a narrower type, like byte. To do this, the extra bytes are just cut off the front of the wider type. Thus, to move from the int 92 to the byte 92, remove the first three bytes from 000000000000-00000000000001011100, leaving 01011100. This cast doesn’t lose information, but other casts can. For example, the int 192 is 00000000000-000000000000011000000. If you cast this to a byte by removing the first three bytes, you get 11000000. Notice the sign bit. This is a negative number, specifically -64. There is no easy way around this problem. The numbers you get in a narrowing cast are not guaranteed to make sense. The simple fact is that you cannot fit 192 into a signed byte.

The two basic rules for conversion between integer data types are as follows:

1.  If the type to be converted to is wider than the type you’re converting from, sign extend the narrower type.
2.  If the type to be converted to is narrower than the type you’re converting from, truncate the most significant bytes of the integer you’re converting.

Conversions to and from the char type behave similarly, once you take account of the fact that char is unsigned. To convert a char to a byte, the high-order byte is truncated. To convert a char to a short, the char is left as is, but is now interpreted as a signed 2-byte integer. To convert to an int or a long, the char is sign extended by two or six bytes respectively. This may produce a negative number where there wasn’t one before if the char value is greater than 32,767 — that is, if its high-order bit is one.

To convert a byte to a char, the byte is sign extended one byte. To convert a short to a char, the short is merely reinterpreted as a signed, 2-byte integer. Finally, to convert an int or long to a char, all but the least-significant 16 bits are truncated. Although converting a char to a short, int, or long may play funny games with the sign, converting it back will return the original char.

The rules for conversions to and from floating-point numbers are more complex. A float can be cast to a double with no loss of precision whatsoever. Double to float conversion presents some problems, though. Some doubles can be exactly represented as floats, but some are too large, some are too small, and some have more precision (that is, a longer mantissa) than a float allows. If the absolute value of the double is larger than can fit in a float, the float becomes infinity — positive or negative depending on the sign of the double. If the absolute value of the double is smaller than can fit in a float (that is, closer to zero), the float becomes zero — positive or negative depending on the sign of the double.

Floats and doubles that are small enough to be represented as ints must fall between two ints; that is, there is an int value larger than the float and an int value smaller than the float. The float is rounded to the int in the pair between which it falls that is closest to zero. Thus, 7.5 is rounded to 7; 7.6 is also rounded to 7, but -7.5 is rounded to -7, not to -8. If the float or double is too large to be represented as an int, for example 6.73E14, then it is rounded to the largest possible int, 2,147,483,647. Similarly, if the float is too small and negative, for example -6.73E14, then it is rounded to the smallest possible int, -2,147,483,648. NaN is rounded to zero. Rounds to longs behave similarly except that the largest and smallest values are quite a bit larger.

Conversions of floats and doubles to shorts and bytes involve a two-step procedure. First the float or double is converted to a double, as described earlier in this chapter. Then the int is converted to a byte or short in the normal way, by truncating the excess bytes in the int. Thus, casting the float 7.5 to a byte results in the value 7. However, casting 175.5 to a byte results in the value -47. This occurs by first rounding 175.5 to 175, 0x000000AF, and then by truncating this to AF, 10101111 in binary. Of course, a byte is signed, so this is equal to -47.

I can think of little reason to want to convert a float or a double to a char, but you can if you need to. The conversion takes place much as with conversions to shorts: the float or double is first converted to an int, which is then converted to a char.


Previous Table of Contents Next
HomeAbout UsSearchSubscribeAdvertising InfoContact UsFAQs
Use of this site is subject to certain Terms & Conditions.
Copyright (c) 1996-1999 EarthWeb Inc. All rights reserved. Reproduction in whole or in part in any form or medium without express written permission of EarthWeb is prohibited. Read EarthWeb's privacy statement.