Internal working of Unary Not Operator (~) - java

public class bitwise_operator {
public static void main(String[] args) {
int var1 = 42;
int var2 = ~var1;
System.out.println(var1 + " " + var2);
}
}
The above code produces 42 -43 as the output.
As far as my understanding goes, Unary Not operator (~), inverts all of the bits of its operand.
Now, 42 in binary is 00101010. On using ~ operator, we get inverted value of 42 i.e. 11010101
If you convert the preceding binary value, the output should be something else and not -43
Tried my luck with different numbers to observe the pattern and found that, the output is 1 number more than the initial value supplied with a leading (-) sign before it, as seen in the above case.
For eg..,
if num is 45 // Output is 45 -46
if num is 1001 // Output is 1001 -1002
Could someone please explain how the Unary Not Operator (~) works internally to output such results?

You are using a signed integer value which is in 2's complement.
Your result is correct: 11010101 is in fact -43:
-2^7 + 2^6 + 2^4 + 2^2 + 2^0 = -128 + 64 + 16 + 4 + 1 = -128 + 85 = -43

This is what's known as two's complement, and it is how integers and all fixed point numbers in Java, C, C++ etc work
-x = ~x + 1
So for example -1 (0xFFFF) negated bitwise (0x0) plus 1 = 0x1

Related

Initialising an integer variable with a bit pattern

im an absolute beginner and have following task that I need to complete but im totally confused and can't find anything online, hope someone can help out.
Task:
Let the variable “pattern” be declared as an integer with 32 bits and
initialised with the bit pattern 0011 1101 0101 1110 0101 1111 0001
1010 (3D5E 5F1A). Print the variable, set Bit 7 to 1 and print again.
Given:
int pattern = ;
boolean ww = false;
int value = 0;
System.out.println("bitpattern = " + pattern + " --> " +Integer.toBinaryString(value));
When I understand that right, an integer is by default declared with 32bit so nothing to do for me for this part. But when I try to assign the number 0011 1101 0101 1110 0101 1111 0001 1010 to the "int pattern" I get the error "integer number too large".
where is my misconception ? Does anyone know a tutorial for that?
Thanks
You can do it like this. The underscores are not required but make it easier to separate nibbles. Prefix the string with 0b.
int a = 0b0011_1101_0101_1110_0101_1111_0001_1010;
System.out.println(Integer.toHexString(a));
prints
3d5e5f1a
If you have a String of bits you can do
String bitStr = "00111101010111100101111100011010";
int v = Integer.parseInt(bitStr, 2);
System.out.println(Integer.toHexString(v));
prints
3d5e5f1a
For longs you must suffix with an L
long longbits = 0b0011110101011110010111110001101000111101010111100101111100011010L;
here are other prefixes available
int hex = 0x2A; // prefix with 0x - 42 in decimal
int octal = 023 // prefix with 0 - 19 in decimal
If you had your input in string-form, you could use Integer.parse(input, 2) see docs.
In your case you could so that: value = Integer.parseInt(String.valueOf(pattern), 2) (enclosed in try catch)

Java implicit conversion between int and char [duplicate]

This question already has answers here:
Calculating with the char variable in java
(2 answers)
Closed 4 years ago.
I'm looking for an explanation for Java's behavior when handling the following scenarios. I understand that the ASCII table is arranged so that the value of the character 5 is five positions greater than 0. This allows for calculations to be done on the char without converting to an int as seen in the first example.
What I don't understand is why Java seems to inconsistently handle when to provide a value from an ASCII table and when to do a calculation on the chars as though they were integers.
int x = '5' - '0';
output x = 5;
int x = '5'
output x = 53;
Now for some examples, that introduce confusion.
int x = '0' + 1 - '5'
output x = -4
int y = '5' - '0' + '1'
output 54
int y = '5' - 0 + '1'
output 102
Java seems to be doing an implicit type conversion, but how is Java inferring which representation of the int/char should it be using?
Just write the char conversion to ASCII code (below your statements)
int x = '0' + 1 - '5'
48 + 1 - 53 = -4
int y = '5' - 0 + '1'
53 - 0 + 49 = 102
int y = '5' - '0' + '1'
53 - 48 + 49 = 54
Notice it's consistent, each int remains int and each char converted to ASCII code
This might seem to be inconsistent but in real they are consistent.
int x = '5' - '0';
output x = 5; because behind the back ASCII codes are, '5'=53 and '0'=48.
Hence
int x = '5'
output x = 53;
You might be mixing the representation from the value. The values never change, so when you perform arithmatic it will always be that '5'==53 and not 5. For the display JLS on primitive to string conversion.
Integer arithmetic is promoted to int for most calculations.
System.out.println('5' + '0');
>>> 101
System.out.println((char)('5' + '0'));
>>> e
Both results have the same numeric value, but one is displayed as a character because it has been cast to character.
Java seems to be doing an implicit type conversion, but how is Java inferring which representation of the int/char should it be using?
It's actually quite simple. char is one of the numeric types in Java, see 4.2.1. Integral Types and Values:
The values of the integral types are integers in the following ranges:
[...]
For char, from '\u0000' to '\uffff' inclusive, that is, from 0 to 65535
All operations on integer types are carried out either with int- or long- precision, see 4.2.2. Integer Operations:
If an integer operator other than a shift operator has at least one operand of type long, then the operation is carried out using 64-bit precision, and the result of the numerical operator is of type long. If the other operand is not long, it is first widened (§5.1.5) to type long by numeric promotion (§5.6).
Otherwise, the operation is carried out using 32-bit precision, and the result of the numerical operator is of type int. If either operand is not an int, it is first widened to type int by numeric promotion.
Note the last sentence: this defines the conversion to be applied, it is called "numeric promotion".
char '0' does not equals int 0. char '0''s binary representation occupies 16 bit:
0000 0000 0011 0000
while int 0's binary representation occupies 32 bit:
0000 0000 0000 0000 0000 0000 0000 0000
When you sum a char and an int, the char will be promoted to int first.
For example. char 5's unicode is 0035, in binary 0000 0000 0011 0101, it will be promoted to int by inserting 16 zeros at head, 0000 0000 0000 0000 0000 0000 0011 0101, and the int represents 53 in decimal.

Convert int which start with leading zero to string

I'm trying to convert int's which start with 0 to strings to be stored in a phone directory as the telephone numbers can start with 0.
I've tried -
int num = 0125;
String.format("%04d",num);
and
Integer.toString(num);
and
DecimalFormat df = new DecimalFormat("0000");
df.format(num);
Each time I get the output 0085 rather than 0125.
How do I convert an int with a leading zero to a string in decimal format?
An int value starting with a zero is considered to be a octal number (having numbers from 0 - 7) similar to hexadecimal numbers. Hence your value:
0125
is equal to: 1 * 82 + 2 * 81 + 5 * 80 == 64 + 16 + 5 == 85
Don't try to represent a phone-number as an int. Instead use a String and validate it using a regex expression. If you combine both, you may as well represent a phone number by its own type like:
public class PhoneNumber {
private final String number;
public PhoneNumber(String number) {
if (number == null || !number.matches("\\d+([-]\\d+)?")) {
throw new .....
}
this.number = number;
}
}
The regex is just an example matching phone numbers like: 1234 or 0123-45678.
A numeric literal that starts with 0 is considered to be Octal (base 8). 125 base 8 is 85 base 10 (decimal).
Also, int i = 09 will throw a compiler error for the same reason.
See 09 is not recognized where as 9 is recognized
0125 is actually 85. Why?
Numbers that starts with 0, are octal numbers. So 0125 is:
5*80 + 2*81 + 1*82 = 85
See the JLS - 3.10.1. Integer 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.

Remainder operator gives negative result

I have a problem with remainder operator in java:
Why this:
(int)2147483648l % 10
gives a negative number (-8)?
That's because (int) 2147483648l is -2147483648. You're casting the long to int and it is out of bounds.
Casting problem .Data loss due to narrowing. You are converting long to int.
Read more about conversion.
From JLS
The remainder operation for operands that are integers after binary numeric promotion (§5.6.2) produces a result value such that (a/b)*b+(a%b) is equal to a.
from Narrowing Primitive Conversions JLS 5.1.3
So 2147483648l will cast into int that will be -2147483648 and then based on (a/b)*b+(a%b) = a
Value should be -8 what you are getting.
use "long" in place of "int".
you can use it without typecasting also
Following Example might be useful:
public class Example1
{
public static void main(String args[])
{
int b = (int)2147483648l;
System.out.println("Value of b: "+ b);
System.out.println("Output1: "+b % 10);
long a = 2147483648l;
System.out.println("Value of a: "+ a);
System.out.println("Output2: "+ a % 10);
}
}
output
Value of b: -2147483648
Output1: -8
Value of a: 2147483648
Output2: 8
You're getting a negative number because you're converting a long to an int. A possible work around in your case simply takes advantage of the fact that any decimal x mod 10 is simply the digit in the lowest decimal place (in the ones place). For example, 156 mod 10 is 6, because 156 divided by 10 is 15 + (6/10). So you could do something like this
//get the number and make it a string
String numberAsString = String.valueOf(number);
//get the integer value of the last character in the string (basically the lowest place)
int mod10 = Integer.parseInt(numberAsString.charAt(numberAsString.length() - 1));
This works for any integer number as long as what you want is number % 10

Why are integer literals with leading zeroes interpreted strangely?

This prints 83
System.out.println(0123)
However this prints 123
System.out.println(123)
Why does it work that way?
A leading zero denotes that the literal is expressed using octal (a base-8 number).
0123 can be converted by doing (1 * 8 * 8) + (2 * 8) + (3), which equals 83 in decimal.
For some reason, octal floats are not available.
Just don't use the leading zero if you don't intend the literal to be expressed in octal.
There is also a 0x prefix which denotes that the literal is expressed in hexadecimal (base 16).
Because integer literals starting with 0 are treated as octal numbers.
See section 3.10.1 of the JLS
Try this:
public static String leftPad(int n, int padding) {
return String.format("%0" + padding + "d", n);
}
leftPad(5, 3); // return "005"
leftPad(15, 5); // return "00015"
leftPad(224, 3); // return "224"
leftPad(0, 4); // return "0000"
first one printed as 83 because java takes 0123 as octal number and it prints decimal equivalent of that number.
The octal (leading 0) and hexadecimal (leading 0x) were inherited from C.
For comparison, try
System.out.println(0x123);
In Java integer literals with a leading zero are octal integers (base 8).
(1 * 8^2) + (2 * 8^1) + (3 * 8^0) = 83
So do not use any number leading with 0 if you don't want to treat it as an octal number.
0123 -> 83
1010L -> 1010
0101L -> 65
The numbers 1010L and 0101L are not in binary representation (just to avoid the confusion).
These numbers are in decimal representation.
Even as per the Regex patterns in Oracle docs,
\0n is the character with octal value 0n (0 <= n <= 7)
\xhh is the character with hexadecimal value 0xhh
Thus, your number 0101 be it in Integer or Long format is treated as an Octal representation of a number.
123 => 1 * 8^2 + 2 * 8^1 + 1 * 8^0 = 83
0101 => 1 * 8^2 + 0 * 8^1 + 1 * 8^0 = 64 + 0 + 1 = 65
printf will do it: http://java.sun.com/developer/technicalArticles/Programming/sprintf/
public class X
{
public static void main(final String[] argv)
{
System.out.printf("%04d", 123);
System.out.println();
}
}
You could also make it "%0" + size + "%d" if you wanted to vary the length... though if the lengths were common I'd probably make constants like "%04d", "%012d", etc...

Categories