I'm reading Core Java by Horstmann.
This is an example:
byte nx = (byte)300;
System.out.println(nx);
The result is 44. I can't understand why? I suppose 2 variants: 1) everything is ruined and you just get a complete garbage; 2) there is some logic.
I'm inclined to the second variant as the book tells me that it is 44 that is received. So, there is some algorithm behind it.
Could you help me understand.
A cast to byte will only retain the least significant 8 bits. 300 (as an int here) in binary is
00000000 00000000 00000001 00101100
Retaining the last 8 bits throws away the most signficant 1 (and everything else before it) which represents 256, so the remaining value is 300 - 256 = 44
00101100
The byte data type is only 8 bits long, and the decimal number 300 requires 9 bits.
When you cast it, you truncated it and cut off the leftmost bit, leaving the binary representation of the decimal number 44.
If you need an analogy, think of casting from a float like 35.6 to an int. Because ints cannot have decimal places, that cast truncates '.6' off of the float, ignoring it completely in the returned value.
Look at the binary expansion of 300:
100101100
Now chop off all but the last 8 bits (the width of a byte in Java):
00101100
Now convert that back to an integer value:
44
Note that you have to be careful about sign bits. You can't just take the remainder after dividing by 256. For instance:
byte nx = (byte)400;
System.out.println(nx);
will print -112 (not 144). That's because the bit pattern after the cast is
10010000
and the left-most (eighth) bit is treated as the sign bit in the two's complement representation of -112.
Related
I've read about overflow, I know that "Overflow is when a number is so large that it will no longer fit within the data type, so the system “wraps around” to the next lowest value and counts up from there".
For example:
short s = (short)1921222; // Stored as 20678
In that example we started counting from -32768 (Short.MIN_VALUE), but when I try to prove in another integer data types, it doesn't seem work the same way...
byte b = (byte)400; // Stored as -112
The example above started counting from 0 that was the only way I found to get -112
I don't know if I am doing something wrong.
The Java Language Specification says:
The integral types are byte, short, int, and long, whose values are 8-bit, 16-bit, 32-bit and 64-bit signed two's-complement integers, respectively, and char, whose values are 16-bit unsigned integers representing UTF-16 code units.
So, short and byte are both two's complement integers.
short is 16 bits, meaning it can hold 2^16 = 65536 different values. After the 65536th value, it overflows.
1921222 modulo 65536 is 20678 . This is less than 32768 (2^15, the turning point for the two's complement) so we keep a positive number.
byte is 8 bits, meaning it can hold 2^8 = 256 different values. This one overflows after the 256hth value.
400 modulo 256 is 144. This value is higher than 128, the turning point for the two's complement - hence it will be interpreted as a negative two's complement number.
The cast is truncating the number. (JLS)
0000 0001 1001 0000
loses the high byte to become
1001 0000
which is -112.
In java, byte primitive type is an 8 bit signed integer, that's why you got -112 from calling:
byte b = (byte) 400;
You can avoid that and get its un-signed value, by binary adding it with 0xFF like this:
int b = (byte) 400 & 0xFF;
For further details you can check:
Java Primitive data types Documentation.
How to Convert Int to Unsigned Byte and Back
In addition to the other answers, you can get to that answer by manual calculation as well.
In Java, the data type byte is an 8-bit, signed integer. So the values are in the interval [-128, 127]. If you have a value of 400 and you want to see the actual value for that type, you can subtract the size of the interval from that number until you reach a value that's inside the interval.
As I said, byte is 8 bit, so the size of the interval is 256. Subtract that from your initial value: 400 - 256 = 144. This value is still outside of the interval so you have to subtract again: 144 - 256 = -112. This value is now inside the interval and is indeed the value you've seen in your test.
The same is true for your first example: short is 16 bit and signed, so the interval is [-32768, 32767] with size 65536. Doing repeated subtraction from the value 1921222 will eventually give you the value 20678 as seen in your test.
I think understand what they fundamentally do - operate on bits (flip, shift, invert, etc...).
My issue is that I don't know when I'd ever need to use them, and I don't think I fully understand bits.
I know that there are 8 bits in a byte and I know that bits are either a 0 or 1. Now here is where I start to get confused... I believe data types define combinations of bits differently. So if I declare an int, 32 bits are set aside for numbers, if I declare a char, 8 bits are set aside and the bits for that data type define a letter.
Running with that idea, I did the following basic operation in java which confuses me:
int num = 00000010;
System.out.println(num);
This prints 8 and if I define num this way:
int num = 00000100;
System.out.println(num);
This prints 64
So to practice with bitwise operations (just for the hell of it) I tried this:
int num = 00000010 << 1;
System.out.println(num);
And it prints 16 where as I thought it would shift the bits by one to the left and print 64.
What is happening here, and when would I ever need to apply this method of manipulating bits?
You are accidentally specifying an octal literal when you specify a number with a leading zero.
00000010 => 1*8^1 + 0*8^0 => 8
00000100 => 1*8^2 + 0*8^1 + 0*8^0 => 64
The JLS, Section 3.10.1, describes octal and binary literals:
An octal numeral consists of an ASCII digit 0 followed by one or more
of the ASCII digits 0 through 7 interspersed with underscores, and can
represent a positive, zero, or negative integer.
A binary numeral consists of the leading ASCII characters 0b or 0B
followed by one or more of the ASCII digits 0 or 1 interspersed with
underscores, and can represent a positive, zero, or negative integer.
You are bit-shifting your 8 by one to the left, effectively multiplying it by 2 to get 16. In bits:
00000100 => 00001000
(8 => 16)
Binary literals are expressed with leading 0b, e.g.:
0b000010 => 2
I'm using cooperative coevolution to solve a couple of function optimisation problems, and am having issues.
The functions take N parameters, where each parameter is a number, and all the functions minimise when each and every one of the N parameters is 0.
My representation of the 'individuals' for use in cooperative coevolution is a binary string, so I can perform bit-flip mutations (it's imperative I keep this representation).
Due to the fact that the functions converge when the parameters are zero, of course -1 is pretty close. However, in 32-bit binary representation, -1 is a string of 32 1s, where 0 is a string of 32 0s. I such get stuck in a local optimum, where some of the parameters are -1 and others are 0.
So my question is, how does one go about avoiding/getting out of this? Is it acceptable to probabilistically flip all 32 bits with a probability equal to that of my mutation rate?
Thanks in advance guys
Using machine internal representation is considered harmful because it leads to deceptive solutions in genetic algorithms.
There are many articles about MDP (Minimal Deceptive Problem) in genetic algoritms that cover this topic, for example:
http://www.dtic.mil/get-tr-doc/pdf?AD=ADA294072
and great David Goldberg's book which explains deceptive problems and MDP and Building Blocks hypothesis (Genetic Algorithms in Search, Optimization, and Machine Learning, David Goldberg).
Internal representation of signed integer is Two's complement which leads to deceptive chromosome encoding where:
11111111 11111111 11111111 11111111 = -1
00000000 00000000 00000000 00000000 = 0
If you want to use this Two's complement encoding, then I suggest to mask most left bit to make individual always positive number and then convert to float number with any offset you want.
For example:
int a = ... // any value from 0 to 0x7fffffff
float x = ( ((float) a) / 0x7fffffff ) * 100 - 50.0;
// now x is in range: -50.0 .. 50.0
Can any please help me to find out the algorithm of calculating latitude and longitude from 8 byte value?
8- byte value - A027AFDF5D984840 and It's longitude is 49.1903648
8- byte value - 3AC7253383DD4B40 and It's latitude is 55.7305664
Also if possible then please tell me how to calculate floating point value of 0000000000805A40 as 106.0
This isn't specific to longitude and latitude calculation. Given that you have 8 bytes to work with in your examples, what you are looking to do is convert a byte array to double precision floating point values. The process is the same for all three examples.
To find the floating point value, you need to deal with the byte array at the bit level. An explanation of the process is here. Or check out Wikipedia.
To get you started, in your first example, you will be dealing with the bytes in the order of 40, 48, 98, 5D and so on. Breaking down the first two bytes, 40 and 48 (0100 0000 0100 1000), you have enough information to get the sign bit (0) and the exponent bit range (100 0000 0100 -> 1028). From here, continue listing out the 52 remaining bits to determine the fractional portion of the number. If you follow the calculations at the links above, you will see the floating point values you expect from your examples.
As a side note, some programming languages provide a method of doing this conversion for you. Depending on what language you are using, there is no need to reinvent the wheel here.
EDIT: Example
To convert the byte array to a double precision floating point value, we will need three pieces of information from the byte array: the sign bit (S), the exponent (E) and the fraction (F). The first thing to do is create your 64 bit representation of the 8 byte array. As I mentioned above, you will use the bytes in "reverse" order (little-endian if you want to do reading on the topic). I will use only the first four bytes as they will be enough to illustrate the process.
40 48 98 5D ==> 01000000 01001000 10011000 01011101
I will refer to the bits above in the order of 0 being leftmost.
Sign bit:
This is the 0th bit in the array above. In this case, S is 0. The sign bit is exactly what you'd think it would be, it determines whether the floating point result will be negative or positive.
Exponent:
Bits 1-11 determine the exponent. In the example, the exponent E is 100 0000 0100 ==> 1028.
Fraction:
The remaining bits, 12-63 determine the fraction. I only illustrated bits 12-31 to show how the process works: 1000 10011000 01011101....
The fractional bits are not converted to a decimal value. Instead, you need to iterate through them paying attention to the bits which are set (1, not 0). The index of the bits is what is important here. Consider the fraction bits indexed starting at 1 increasing from left to right to 20. Again, in the full example (bits 12-63), this indexing would be 1 to 52.
The fraction is found by summing each i'th bit that is set using this expression: 2^-i. For this example this means we are dealing with indexes 1,5,8,9,14,16,17,18,20.
The first four indexes will give us enough precision for the purposes of the example:
F = (2^-1) + (2^-5) + (2^-8) + (2^-9) + ... = 0.5 + 0.03125 + 0.00390625 + 0.001953125 = 0.537109375
The final value V is found by applying the formula:
V = -1^S * 2^(E-1023) * (1 + F) = -1^0 + 2^(1028-1023) * 1.537109375 = 49.1875
This is a good approximation of your goal value of 49.1903648. If you were to continue using the full fractional bit range in the manner I showed you, your final value will match.
Lastly, since you mentioned you are using Java, have you taken a look at using the ByteBuffer class and the getDouble function here?
Need a solution on how to perform the following: receive a decimal value, convert it to 32-bit Hex, then separate that 32-bit hex and get high 16-bit and low 16-bit values. I have been digging around net and cannot find much info.
Not sure why you are converting to hex but to turn a 32-bit value straight into two 16-bit values.
int x = ...
short high = x >> 16;
short low = x & 0xFFFF;
I expect this is a homework problem. Accordingly, I will give you information that can help you solve it rather than a solution.
Convert the number to hexadecimal. This can be done with the Integer's toHexString() method.
Add enough zeroes to the left to make it eight characters long (8 hexadecimal characters represent 32 bits). You can do this by adding zeroes one by one in a loop until it's 8 characters long, or (better approach) just add 7 zeroes to the left and only deal with the rightmost 8 characters.
Take the the rightmost 4 characters as the lower 16 bits and the 4 characters immediately to the left of that as the higher 16 bits. This can be done with the String's substring() method along with length() and some simple subtraction.
Some APIs you might find useful:
http://download.oracle.com/javase/6/docs/api/java/io/DataInputStream.html
http://download.oracle.com/javase/6/docs/api/java/lang/Integer.html#parseInt(java.lang.String, int)
http://download.oracle.com/javase/6/docs/api/java/lang/Integer.html#toHexString(int)
http://commons.apache.org/codec/apidocs/org/apache/commons/codec/binary/Hex.html