how to convert negative number to binary in java? - java

I'm trying to convert a negative long number (e.g. -1065576264718330231L) to binary.
First, I convert negative number to positive one by removing the sign;
Second, I get the binary of the result from first step;
then I get stuck with "add one" to the binary result of the second step,that is :
please! how to implement the third step?
or do you have other better solutions?!
http://geekexplains.blogspot.com/2009/05/binary-rep-of-negative-numbers-in-java.html

Signed integers/longs use the two-complements notation:
Say you have -6:
6 = 000..000 110 binary
111..111 001 one's complement
111..111 010 add 1
-6 = 111..111 010
The advantage is that normal binary addition works (-6+6=0), there is just one 0.
Of you could simply subtract 6 from 0:
000
110
------ -
0
1 borrow 1 (all ones at the top)
0
...111
111...111010 = -6
Note:
If one borrows (subtracts one of) 0000000, one actually uses an overflow:
(1)0000000 which minus 1 delivers
1111111
Goodies:
long n = -1065576264718330231L;
System.out.println(Long.toUnsignedString(n, 2));
System.out.println(Long.toString(n, 2));

Given the long value is -1065576264718330231L.
long v = -1065576264718330231L;
System.out.println(Long.toBinaryString(v));
Or you can code the algorithm yourself
StringBuilder sb = new StringBuilder();
while (v != 0) {
sb.append(v < 0 ? '1'
: '0');
v <<= 1;
}
System.out.println(sb.toString());
If you want to convert a positive number to negative using 2's complement you can do the following:
long pos = 23;
long neg = ~pos + 1;
System.out.println(pos);
System.out.println(neg);
But all Strings, ints, longs, etc. are inherently stored in binary and are displayed in different formats based on context.

Related

How to convert large integer number to binary?

Sorry for a possible duplicate post, I saw many similar topics here but none was exactly I needed. Before actually posting a question I want to explicitly state that this question is NOT A HOMEWORK.
So the question is: how to convert a large integer number into binary representation? The integer number is large enough to fit in primitive type (Java long cannot be used). An input might be represented as a string format or as an array of digits. Disclaimer, This is not going to be a solution of production level, so I don't want to use BigInteger class. Instead, I want to implement an algorithm.
So far I ended up with the following approach:
Input and output values represented as strings. If the last digit of input is even, I prepend the output with "0", otherwise - with "1". After that, I replace input with input divided by 2. I use another method - divideByTwo for an arithmetical division. This process runs in a loop until input becomes "0" or "1". Finally, I prepend input to the output. Here's the code:
Helper Method
/**
* #param s input integer value in string representation
* #return the input divided by 2 in string representation
**/
static String divideByTwo(String s)
{
String result = "";
int dividend = 0;
int quotent = 0;
boolean dividendIsZero = false;
while (s.length() > 0)
{
int i = 1;
dividend = Character.getNumericValue(s.charAt(0));
while (dividend < 2 && i < s.length())
{
if (dividendIsZero) {result += "0";}
dividend = Integer.parseInt(s.substring(0, ++i));
}
quotent = dividend / 2;
dividend -= quotent * 2;
dividendIsZero = (dividend == 0);
result += Integer.toString(quotent);
s = s.substring(i);
if (!dividendIsZero && s.length() != 0)
{
s = Integer.toString(dividend) + s;
}
}
return result;
}
Main Method
/**
* #param s the integer in string representation
* #return the binary integer in string representation
**/
static String integerToBinary(String s)
{
if (!s.matches("[0-9]+"))
{
throw new IllegalArgumentException(s + " cannot be converted to integer");
}
String result = "";
while (!s.equals("0") && !s.equals("1"))
{
int lastDigit = Character.getNumericValue(s.charAt(s.length()-1));
result = lastDigit % 2 + result; //if last digit is even prepend 0, otherwise 1
s = divideByTwo(s);
}
return (s + result).replaceAll("^0*", "");
}
As you can see, the runtime is O(n^2). O(n) for integerToBinary method and O(n) for divideByTwo that runs inside the loop. Is there a way to achieve a better runtime? Thanks in advance!
Try this:
new BigDecimal("12345678901234567890123456789012345678901234567890").toString(2);
Edit:
For making a big-number class, you may want to have a look at my post about this a week ago. Ah, the question was by you, never mind.
The conversion between different number systems in principle is a repeated "division, remainder, multiply, add" operation. Let's look at an example:
We want to convert 123 from decimal to a base 3 number. What do we do?
Take the remainder modulo 3 - prepend this digit to the result.
Divide by 3.
If the number is bigger than 0, continue with this number at step 1
So it looks like this:
123 % 3 == 0. ==> The last digit is 0.
123 / 3 == 41.
41 % 3 == 2 ==> The second last digit is 2.
41 / 3 == 13
13 % 3 == 1 ==> The third digit is 1.
13 / 3 == 4
4 % 3 == 1 ==> The fourth digit is 1 again.
4 / 3 == 1
1 % 3 == 1 ==> The fifth digit is 1.
So, we have 11120 as the result.
The problem is that for this you need to have already some kind of division by 3 in decimal format, which is usually not the case if you don't implement your number in a decimal-based format (like I did in the answer to your last question linked above).
But it works for converting from your internal number format to any external format.
So, let's look at how we would do the inverse calculation, from 11120 (base 3) to its decimal equivalent. (Base 3 is here the placeholder for an arbitrary radix, Base 10 the placeholder for your internal radix.) In principle, this number can be written as this:
1 * 3^4 + 1 * 3^3 + 1*3^2 + 2*3^1 + 0*3^0
A better way (faster to calculate) is this:
((((1 * 3) + 1 )*3 + 1 )*3 + 2)*3 + 0
1
3
4
12
13
39
41
123
123
(This is known as Horner scheme, normally used for calculating values of polynomials.)
You can implement this in the number scheme you are implementing, if you know how to represent the input radix (and the digits) in your target system.
(I just added such a calculation to my DecimalBigInt class, but you may want to do the calculations directly in your internal data structure instead of creating a new object (or even two) of your BigNumber class for every decimal digit to be input.)
Among the simple methods there are two possible approaches (all numbers that appear here decimal)
work in decimal and divide by 2 in each step as you outlined in the question
work in binary and multiply by 10 in each step for example 123 = ((1 * 10) + 2) * 10 + 3
If you are working on a binary computer the approach 2 may be easier.
See for example this post for a more in-depth discussion of the topic.
In wikipedia, it is said:
For very large numbers, these simple methods are inefficient because
they perform a large number of multiplications or divisions where one
operand is very large. A simple divide-and-conquer algorithm is more
effective asymptotically: given a binary number, it is divided by
10^k, where k is chosen so that the quotient roughly equals the
remainder; then each of these pieces is converted to decimal and the
two are concatenated. Given a decimal number, it can be split into two
pieces of about the same size, each of which is converted to binary,
whereupon the first converted piece is multiplied by 10^k and added to
the second converted piece, where k is the number of decimal digits in
the second, least-significant piece before conversion.
I have tried, this method is faster than conventional one for numbers larger than 10,000 digits.

Why does i = i + i give me 0?

I have a simple program:
public class Mathz {
static int i = 1;
public static void main(String[] args) {
while (true){
i = i + i;
System.out.println(i);
}
}
}
When I run this program, all I see is 0 for i in my output. I would have expected the first time round we would have i = 1 + 1, followed by i = 2 + 2, followed by i = 4 + 4 etc.
Is this due to the fact that as soon as we try to re-declare i on the left hand-side, its value gets reset to 0?
If anyone can point me into the finer details of this that would be great.
Change the int to long and it seems to be printing numbers as expected. I'm surprised at how fast it hits the max 32-bit value!
Introduction
The problem is integer overflow. If it overflows, it goes back to the minimum value and continues from there. If it underflows, it goes back to the maximum value and continues from there. The image below is of an Odometer. I use this to explain overflows. It's a mechanical overflow but a good example still.
In an Odometer, the max digit = 9, so going beyond the maximum means 9 + 1, which carries over and gives a 0 ; However there is no higher digit to change to a 1, so the counter resets to zero. You get the idea - "integer overflows" come to mind now.
The largest decimal literal of type int is 2147483647 (231-1). All
decimal literals from 0 to 2147483647 may appear anywhere an int
literal may appear, but the literal 2147483648 may appear only as the
operand of the unary negation operator -.
If an integer addition overflows, then the result is the low-order
bits of the mathematical sum as represented in some sufficiently large
two's-complement format. If overflow occurs, then the sign of the
result is not the same as the sign of the mathematical sum of the two
operand values.
Thus, 2147483647 + 1 overflows and wraps around to -2147483648. Hence int i=2147483647 + 1 would be overflowed, which isn't equal to 2147483648. Also, you say "it always prints 0". It does not, because http://ideone.com/WHrQIW. Below, these 8 numbers show the point at which it pivots and overflows. It then starts to print 0s. Also, don't be surprised how fast it calculates, the machines of today are rapid.
268435456
536870912
1073741824
-2147483648
0
0
0
0
Why integer overflow "wraps around"
Original PDF
The issue is due to integer overflow.
In 32-bit twos-complement arithmetic:
i does indeed start out having power-of-two values, but then overflow behaviors start once you get to 230:
230 + 230 = -231
-231 + -231 = 0
...in int arithmetic, since it's essentially arithmetic mod 2^32.
No, it does not print only zeros.
Change it to this and you will see what happens.
int k = 50;
while (true){
i = i + i;
System.out.println(i);
k--;
if (k<0) break;
}
What happens is called overflow.
static int i = 1;
public static void main(String[] args) throws InterruptedException {
while (true){
i = i + i;
System.out.println(i);
Thread.sleep(100);
}
}
out put:
2
4
8
16
32
64
...
1073741824
-2147483648
0
0
when sum > Integer.MAX_INT then assign i = 0;
Since I don't have enough reputation I cannot post the picture of the output for the same program in C with controlled output, u can try yourself and see that it actually prints 32 times and then as explained due to overflow i=1073741824 + 1073741824 changes to
-2147483648 and one more further addition is out of range of int and turns to Zero .
#include<stdio.h>
#include<conio.h>
int main()
{
static int i = 1;
while (true){
i = i + i;
printf("\n%d",i);
_getch();
}
return 0;
}
The value of i is stored in memory using a fixed quantity of binary digits. When a number needs more digits than are available, only the lowest digits are stored (the highest digits get lost).
Adding i to itself is the same as multiplying i by two. Just like multiplying a number by ten in decimal notation can be performed by sliding each digit to the left and putting a zero on the right, multiplying a number by two in binary notation can be performed the same way. This adds one digit on the right, so a digit gets lost on the left.
Here the starting value is 1, so if we use 8 digits to store i (for example),
after 0 iterations, the value is 00000001
after 1 iteration , the value is 00000010
after 2 iterations, the value is 00000100
and so on, until the final non-zero step
after 7 iterations, the value is 10000000
after 8 iterations, the value is 00000000
No matter how many binary digits are allocated to store the number, and no matter what the starting value is, eventually all of the digits will be lost as they are pushed off to the left. After that point, continuing to double the number will not change the number - it will still be represented by all zeroes.
It is correct, but after 31 iterations, 1073741824 + 1073741824 doesn't calculate correctly (overflows) and after that prints only 0.
You can refactor to use BigInteger, so your infinite loop will work correctly.
public class Mathz {
static BigInteger i = new BigInteger("1");
public static void main(String[] args) {
while (true){
i = i.add(i);
System.out.println(i);
}
}
}
For debugging such cases it is good to reduce the number of iterations in the loop. Use this instead of your while(true):
for(int r = 0; r<100; r++)
You can then see that it starts with 2 and is doubling the value until it is causing an overflow.
I'll use an 8-bit number for illustration because it can be completely detailed in a short space. Hex numbers begin with 0x, while binary numbers begin with 0b.
The max value for an 8-bit unsigned integer is 255 (0xFF or 0b11111111).
If you add 1, you would typically expect to get: 256 (0x100 or 0b100000000).
But since that's too many bits (9), that's over the max, so the first part just gets dropped, leaving you with 0 effectively (0x(1)00 or 0b(1)00000000, but with the 1 dropped).
So when your program runs, you get:
1 = 0x01 = 0b1
2 = 0x02 = 0b10
4 = 0x04 = 0b100
8 = 0x08 = 0b1000
16 = 0x10 = 0b10000
32 = 0x20 = 0b100000
64 = 0x40 = 0b1000000
128 = 0x80 = 0b10000000
256 = 0x00 = 0b00000000 (wraps to 0)
0 + 0 = 0 = 0x00 = 0b00000000
0 + 0 = 0 = 0x00 = 0b00000000
0 + 0 = 0 = 0x00 = 0b00000000
...
The largest decimal literal of type int is 2147483648 (=231). All decimal literals from 0 to 2147483647 may appear anywhere an int literal may appear, but the literal 2147483648 may appear only as the operand of the unary negation operator -.
If an integer addition overflows, then the result is the low-order bits of the mathematical sum as represented in some sufficiently large two's-complement format. If overflow occurs, then the sign of the result is not the same as the sign of the mathematical sum of the two operand values.

bitwise operation to extract each individual word from a long

I have a long that corresponds to an assembly language instruction.
Here's the problem; the first field is Opcode. It can be either 1 or 2 digits. So for example in 120602, 12 is the opcode. In 10602, 1 is the opcode.
I want to extract each individual field; where opcode is the first 1-2 numbers on the left, 1 to the right of that is op1mode, 1 to the right of that is op1gpr, 1 to the right of that is op2mode, and finally, the last part is op2gpr.
Ideally, I want to assign each to its own variable for later use, or separate them in an array.
I was thinking that this can be achievable using bitwise operations; namely masks and shifts.
How would one split the number with just bitwise operations?
Bitwise/bitshifts won't do you any good unless the fields are combined in a base 2 representation. As shown, your digits are base 10. On the other hand, you can use integer division and modulo for the numbers you've shown.
120602 / 10000 = 12
120602 % 10000 = 602
These basically correspond to the following types of operations for binary digits:
0x1D71A >>> 12 = 0x1D
0x1D71A & 0xFFF = 0x71A
An easy way to do that (but without bit manipulation), is to define an array containing five integers, and then to fill it which the digits of your number. You will have to begin from the end of the number, it is easier.
An example in Java:
long number = 120602;
int[] op = new int[5];
for(int i = 0; i < 4; ++i) {
op[i] = (int) (number % 10);
number /= 10;
}
op[4] = (int) number;
And here:
op[0] is op2gpr
op[1] is op2mode
op[2] is op1gpr
op[3] is op1mode
op[4] is opcode

Restricting Binary Output to 8 bits or 4 bits

Here is my FIRST Question
Here is my code:
public class Bits{
public static void main(String args[]){
int i = 2 , j = 4;
int allOnes = ~0;
int left = allOnes << (j+1);
System.out.println("Binary Equivalent at this stage: " +Integer.toBinaryString(left));
}
}
The following is the output I'm getting:
Binary Equivalent at this stage: 11111111111111111111111111100000
How can I restrict it to only 8 bits from the right hand side. I mean 11100000 .
Please explain.
Here is my SECOND Question:
Also, I have one more Question which is totally different with the above one:
public static void main(String args[]){
int i = 2 , j = 4;
int allOnes = ~0; // will equal sequence of all 1s
int left = allOnes << (j+1);
System.out.println("Binary Equivalent at this stage: " +Integer.toBinaryString(left));
}
}
Since I didn't understand the following line:
int allOnes = ~0; // will equal sequence of all 1s
When I tried to output the value of "allOnes" then I got "-1" as my output.
I'm having hard time understanding the very next line which is as follows:
int left = allOnes << (j+1);
int allOnes = ~0;
Takes the integer 0 and applies the NOT operation bitwise so it will have all ones in its binary representation. Intagers use the two's complement format, meaning that a value of a word having all bits as one is value of -1.
If you only care about byte boundaries, then use a ByteBuffer
byte lastByte = ByteBuffer.allocate(4).putInt(i).array()[3];
To restrict this byte to the first four or last four bits, use lastByte & 0b11110000 or lastByte & 0b00001111
The integer representation of -1 is all 1's, i.e. 32 bits all set to 1. You can think of the first bit as -2^31 (note the negative sign), and of each subsequent bit as 2^30, 2^29, etc. Adding 2^0 + 2^1 + 2^2 ... + 2^30 - 2^31 = -1.
I suggest reading this tutorial on bitwise operations.
For #1 Integer.toBinaryString(left) is printing 32 bits (length of Integer), so if you just want the right 8 you can do the following:
Integer.toBinaryString(left).substring(24)
The ~ operator in Java inverts the the bit pattern. Thus 0 turns into ffff.
The << operator shifts the bits by x. You are shifting the bits to the left by 5 so you end up with 5 zeros on the right.
Here are all the bitwise operators for Java
First, a more general solution for the first question than what I've seen so far is
left &= (2 ^ n) - 1;
where n is the number of binary digits that you want to take from the right. This is based around the bitwise AND operator, &, which compares corresponding bits in two numbers and outputs a 1 if they are both 1s and 0 otherwise. For example:
10011001 & 11110000 == 10010000; // true
This is used to create what are known as bitmasks (http://en.wikipedia.org/wiki/Mask_(computing)). Notice how in this example how the left 4 bits of the first number are copied over to the result and how those same 4 bits are all ones in the second number? That's the idea in a bit mask.
So in your case, let's look at n = 8
left &= (2 ^ 8) - 1;
left &= 256 - 1;
left &= 255; // Note that &=, like += or *=, just means left = left & 255
// Also, 255 is 11111111 in binary so it can be used as the bitmask for
// the 8 rightmost bits.
Integer.toBinaryString(left) = "11100000";
Your second question is much more in depth, but you'd probably benefit most from reading the Wikipedia article (http://en.wikipedia.org/wiki/Two's_complement) instead of trying to understand a brief explanation here.
8 bits in decimal has a maximum value of 255. You can use the modulo (remainder) division operator to limit it to 8 bits at this point. For isntance:
int yournum = 35928304284 % 256;
will limit yournum to 8 bits of length. Additionally, as suggested in the comments, you can do this:
int yournum = 3598249230 & 255;
This works as well, and is actually preferred in this case, because it is much faster. The bitwise and function returns 1 if both associated bits are 1; since only the last 8 bits of 255 are one, the integer is implicitly limited to 255.
To answer your second question: A tilde is the bitwise inversion operator. Thus,
int allOnes = ~0;
creates an integer of all 1s. Because of the way twos complements works, that number actually represents -1.

Better algorithm for complementing integer value excluding the leading zero binary bits

I will explain first what I mean by "complementing integer value excluding the leading zero binary bits" (from now on, I will call it Non Leading Zero Bits complement or NLZ-Complement for brevity).
For example, there is integer number 92. the binary number is 1011100. If we perform normal bitwise-NOT or Complement, the result is: -93 (signed integer) or 11111111111111111111111110100011 (binary). That's because the leading zero bits are being complemented too.
So, for NLZ-Complement, the leading zero bits are not complemented, then the result of NLZ-complementing of 92 or 1011100 is: 35 or 100011 (binary). The operation is performed by XORing the input value with sequence of 1 bits as much as the non-leading zero value. The illustration:
92: 1011100
1111111 (xor)
--------
0100011 => 35
I had made the java algorithm like this:
public static int nonLeadingZeroComplement(int n) {
if (n == 0) {
return ~n;
}
if (n == 1) {
return 0;
}
//This line is to find how much the non-leading zero (NLZ) bits count.
//This operation is same like: ceil(log2(n))
int binaryBitsCount = Integer.SIZE - Integer.numberOfLeadingZeros(n - 1);
//We use the NLZ bits count to generate sequence of 1 bits as much as the NLZ bits count as complementer
//by using shift left trick that equivalent to: 2 raised to power of binaryBitsCount.
//1L is one value with Long literal that used here because there is possibility binaryBitsCount is 32
//(if the input is -1 for example), thus it will produce 2^32 result whom value can't be contained in
//java signed int type.
int oneBitsSequence = (int)((1L << binaryBitsCount) - 1);
//XORing the input value with the sequence of 1 bits
return n ^ oneBitsSequence;
}
I need an advice how to optimize above algorithm, especially the line for generating sequence of 1 bits complementer (oneBitsSequence), or if anyone can suggest better algorithm?
UPDATE: I also would like to know the known term of this non-leading zero complement?
You can get the highest one bit through the Integer.highestOneBit(i) method, shift this one step left, and then subtract 1. This gets you the correct length of 1s:
private static int nonLeadingZeroComplement(int i) {
int ones = (Integer.highestOneBit(i) << 1) - 1;
return i ^ ones;
}
For example,
System.out.println(nonLeadingZeroComplement(92));
prints
35
obviously #keppil has provided shortest solution. Another solution could be like.
private static int integerComplement(int n){
String binaryString = Integer.toBinaryString(n);
String temp = "";
for(char c: binaryString.toCharArray()){
if(c == '1'){
temp += "0";
}
else{
temp += "1";
}
}
int base = 2;
int complement = Integer.parseInt(temp, base);
return complement;
}
For example,
System.out.println(nonLeadingZeroComplement(92));
Prints answer as 35

Categories

Resources