Related
In the following program , I am assigning a integer data type to a char data type.
public static void main(String args[]) {
char ch =65;
System.out.println(ch);
}
I know the fact that int occupies 32 bits and char occupies 16 bits . With that knowledge , I was expecting the compiler throw an error of some message "Attempt to convert a data of higher size to a lower size ".
Why is the compiler not complaining and internally converting and printing the output as 'A' (I understand the fact that it is the ASCII equivalent of 65, my question is only related to the size of data types) ?
The compiler does in fact validate the range. That is working because int 65 is within the expected range.
The following won't compile:
char c = (int)Character.MAX_VALUE + 1
char c = 65536
And this will, just like your assignment:
char c = 65535 //Within range
When the value is not a constant at compile time, though, there's need for cast:
private static void charRange(int i) {
char c = (char) i;
System.out.println(" --> " + (int) c);
}
charRange(65);
charRange(Character.MAX_VALUE + 20);
And the check doesn't happen (making room for overflow)
--> 65
--> 19
There is an exception to Java's general rule about converting an int to a char. If the int is a compile time constant expression (e.g. a literal) AND the int value of the expression is within the required range (0 to 65535), then it is legal to assign the int expression to a char.
Intuitively, for a compile-time constant expression, the compiler knows if the expression value can be assigned without loss of information.
This is covered by JLS 5.2 ... in the paragraph that starts "In addition, if the expression is a constant expression ..."
Programing languages like Java or C# come with a set of integer primitive types. Each type has a well-defined range in the form of [min value, max value]. This values are stored in a fixed sequence of bits from most significant bit to the least one.
For example, let the decimal number 123456 be represented for the next 32 bit sequence
0000000000000011110001001000000
When you attempt to convert a 32-bit number type to a 16-bit one, the compiler copies the 16 least significant bits (or the last 16 bits) then 123456 number is wrapped to
1110001001000000
And if you convert this binary number to decimal it is 57920. As you realize, the 32-bit number cant fit into a 16-bit sequence, and the original sequence was arbitrarily wrapped. This is known as integer overflow, and also happens when you add or multiply 2 number which result is out of bounds of the integer type range.
As programmer, you should be aware of overflow, and react to this to avoid a program failure. You also should read further details about signed integer representation.
I was recently looking into some problems with but manipulation in Java and I came up with two questions.
1) Firstly, I came up to the problem of flipping all the bits in a number.
I found this solution:
public class Solution {
public int flipAllBits(int num) {
int mask = (1 << (int)Math.floor(Math.log(num)/Math.log(2))+1) - 1;
return num ^ mask;
}
}
But what happens when k = 32 bits? Can the 1 be shifted 33 times?
What I understand from the code (although it doesn't really make sense), the mask is 0111111.(31 1's)....1 and not 32 1's, as someone would expect. And therefore when num is a really large number this would fail.
2) Another question I had was determining when something is a bit sequence in 2s complement or just a normal bit sequence. For example I read that 1010 when flipped is 0110 which is -10 but also 6. Which one is it and how do we know?
Thanks.
1) The Math object calls are not necessary. Flipping all the bits in any ordinal type in Java (or C) is not an arithmatic operation. It is a bitwise operation. Using the '^' operator, simply using 1- as an operand will work regardless of the sizeof int in C/C++ or a Java template with with the ordinal type as a parameter T. The tilde '~' operator is the other option.
T i = 0xf0f0f0f0;
System.out.println(T.toHexString(i));
i ^= -1;
System.out.println(T.toHexString(i));
i = ~ i;
System.out.println(T.toHexString(i));
2) Since the entire range of integers maps to the entire range of integers in a 2's compliment transform, it is not possible to detect whether a number is or is not 2's complement unless one knows the range of numbers from which the 2's complement might be calculated and the two sets (before and after) are mutually exclusive.
That mask computation is fairly inscrutable, I'm going to guess that it (attempts to, since you mention it's wrong) make a mask up to and including the highest set bit. Whether that's useful for "flipping all bits" is an other possible point of discussion, since to me at least, "all bits" means all 32 of them, not some number that depends on the value. But if that's what you want then that's what you want. Especially combined with that second question, that looks like a mistake to me, so you'd be implementing the wrong thing from the start - see near the bottom.
Anyway, the mask can be generated with some reasonably nice bitmath, which does not create any doubt about possible edge cases (eg Math.log(0) is probably bad, and k=32 corresponds with negative numbers which are also probably bad to put into a log):
int m = num | (num >> 16);
m |= m >> 8;
m |= m >> 4;
m |= m >> 2;
m |= m >> 1;
return num ^ m;
Note that this function has odd properties, it almost always returns an unsigned-lower number than went in, except at 0. It flips bits so the name is not completely wrong, but flipAllBits(flipAllBits(x)) != x (usually), while the name suggests it should be an involution.
As for the second question, there is nothing to determine. Two's complement is scheme by which you can interpret a bitvector - any bitvector. So it's really a choice you make; to interpret a given bitvector that way or some other way. In Java the "default" interpretation is two's complement (eg toString will print an int by interpreting it according to its two's complement meaning), but you don't have to go along with it, you can (with care) treat int as unsigned, or as an array of booleans, or several bitfields packed together, etc.
If you wanted to invert all the bits but made the common mistake to assume that the number of bits in an int is variable (and that you therefore needed to compute a mask that covers "all bits"), I have some great news for you, because inverting all bits is a lot easier:
return ~num;
If you were reading "invert all bits" in the context of two's complement, it would have the above meaning, so all bits, including those left of the highest set bit.
Is there a way to declare an unsigned int in Java?
Or the question may be framed as this as well:
What is the Java equivalent of unsigned?
Just to tell you the context I was looking at Java's implementation of String.hashcode(). I wanted to test the possibility of collision if the integer were 32 unsigned int.
Java does not have a datatype for unsigned integers.
You can define a long instead of an int if you need to store large values.
You can also use a signed integer as if it were unsigned. The benefit of two's complement representation is that most operations (such as addition, subtraction, multiplication, and left shift) are identical on a binary level for signed and unsigned integers. A few operations (division, right shift, comparison, and casting), however, are different. As of Java SE 8, new methods in the Integer class allow you to fully use the int data type to perform unsigned arithmetic:
In Java SE 8 and later, you can use the int data type to represent an unsigned 32-bit integer, which has a minimum value of 0 and a maximum value of 2^32-1. Use the Integer class to use int data type as an unsigned integer. Static methods like compareUnsigned, divideUnsigned etc have been added to the Integer class to support the arithmetic operations for unsigned integers.
Note that int variables are still signed when declared but unsigned arithmetic is now possible by using those methods in the Integer class.
Whether a value in an int is signed or unsigned depends on how the bits are interpreted - Java interprets bits as a signed value (it doesn't have unsigned primitives).
If you have an int that you want to interpret as an unsigned value (e.g. you read an int from a DataInputStream that you know should be interpreted as an unsigned value) then you can do the following trick.
int fourBytesIJustRead = someObject.getInt();
long unsignedValue = fourBytesIJustRead & 0xffffffffL;
Note, that it is important that the hex literal is a long literal, not an int literal - hence the 'L' at the end.
We needed unsigned numbers to model MySQL's unsigned TINYINT, SMALLINT, INT, BIGINT in jOOQ, which is why we have created jOOU, a minimalistic library offering wrapper types for unsigned integer numbers in Java. Example:
import static org.joou.Unsigned.*;
// and then...
UByte b = ubyte(1);
UShort s = ushort(1);
UInteger i = uint(1);
ULong l = ulong(1);
All of these types extend java.lang.Number and can be converted into higher-order primitive types and BigInteger. Hope this helps.
(Disclaimer: I work for the company behind these libraries)
For unsigned numbers you can use these classes from Guava library:
UnsignedInteger
UnsignedLong
They support various operations:
plus
minus
times
mod
dividedBy
The thing that seems missing at the moment are byte shift operators. If you need those you can use BigInteger from Java.
Perhaps this is what you meant?
long getUnsigned(int signed) {
return signed >= 0 ? signed : 2 * (long) Integer.MAX_VALUE + 2 + signed;
}
getUnsigned(0) → 0
getUnsigned(1) → 1
getUnsigned(Integer.MAX_VALUE) → 2147483647
getUnsigned(Integer.MIN_VALUE) → 2147483648
getUnsigned(Integer.MIN_VALUE + 1) → 2147483649
Use char for 16 bit unsigned integers.
There are good answers here, but I don’t see any demonstrations of bitwise operations. Like Visser (the currently accepted answer) says, Java signs integers by default (Java 8 has unsigned integers, but I have never used them). Without further ado, let‘s do it...
RFC 868 Example
What happens if you need to write an unsigned integer to IO? Practical example is when you want to output the time according to RFC 868. This requires a 32-bit, big-endian, unsigned integer that encodes the number of seconds since 12:00 A.M. January 1, 1900. How would you encode this?
Make your own unsigned 32-bit integer like this:
Declare a byte array of 4 bytes (32 bits)
Byte my32BitUnsignedInteger[] = new Byte[4] // represents the time (s)
This initializes the array, see Are byte arrays initialised to zero in Java?. Now you have to fill each byte in the array with information in the big-endian order (or little-endian if you want to wreck havoc). Assuming you have a long containing the time (long integers are 64 bits long in Java) called secondsSince1900 (Which only utilizes the first 32 bits worth, and you‘ve handled the fact that Date references 12:00 A.M. January 1, 1970), then you can use the logical AND to extract bits from it and shift those bits into positions (digits) that will not be ignored when coersed into a Byte, and in big-endian order.
my32BitUnsignedInteger[0] = (byte) ((secondsSince1900 & 0x00000000FF000000L) >> 24); // first byte of array contains highest significant bits, then shift these extracted FF bits to first two positions in preparation for coersion to Byte (which only adopts the first 8 bits)
my32BitUnsignedInteger[1] = (byte) ((secondsSince1900 & 0x0000000000FF0000L) >> 16);
my32BitUnsignedInteger[2] = (byte) ((secondsSince1900 & 0x000000000000FF00L) >> 8);
my32BitUnsignedInteger[3] = (byte) ((secondsSince1900 & 0x00000000000000FFL); // no shift needed
Our my32BitUnsignedInteger is now equivalent to an unsigned 32-bit, big-endian integer that adheres to the RCF 868 standard. Yes, the long datatype is signed, but we ignored that fact, because we assumed that the secondsSince1900 only used the lower 32 bits). Because of coersing the long into a byte, all bits higher than 2^7 (first two digits in hex) will be ignored.
Source referenced: Java Network Programming, 4th Edition.
It seems that you can handle the signing problem by doing a "logical AND" on the values before you use them:
Example (Value of byte[] header[0] is 0x86 ):
System.out.println("Integer "+(int)header[0]+" = "+((int)header[0]&0xff));
Result:
Integer -122 = 134
Just made this piece of code, wich converts "this.altura" from negative to positive number. Hope this helps someone in need
if(this.altura < 0){
String aux = Integer.toString(this.altura);
char aux2[] = aux.toCharArray();
aux = "";
for(int con = 1; con < aux2.length; con++){
aux += aux2[con];
}
this.altura = Integer.parseInt(aux);
System.out.println("New Value: " + this.altura);
}
You can use the Math.abs(number) function. It returns a positive number.
This is a really basic question, but I've never fully convinced myself that my intuitive answer of "it makes no difference" is correct, so maybe someone has a good way to understand this:
If all I want to do with one of the primitive numeric types in Java is bitwise arithmetic, can I simply treat it as if it was an unsigned value or do I need to avoid negative numbers, i.e. keep the highest order bit always set to 0? For example, can I use an int as if it was an unsigned 32-bit number, or should I only use the lowest 31 bits?
I'm looking for as general an answer as possible, but let me give an example: Let's say I want to store 32 flags. Can I store all of them in a single int, if I use something like
store = store & ~(1 << index) | (value << index)
to set flag index to value and something like
return (store & (1 << index)) != 0
to retrieve flag index? Or could I run into any sort of issues with this or similar code if I ever set the flag with index 31 to 1?
I know I need to always be using >>> instead of >> for right shifting, but is this the only concern? Or could there be other things going wrong related to the two's complement representation of negative numbers when I use the highest bit?
I know I need to always be using >>> instead of >> for right shifting, but is this the only concern?
Yes, this is the only concern. Shifting left works the same on signed and unsigned numbers; same goes for ANDing, ORing, and XORing. As long as you use >>> for shifting right, you can use all 32 bits of a signed int.
There are legitimate reasons to use >> as well in that context (a common case is when making a mask that should be 0 or -1 directly, without having to negate a mask that is 0 or 1), so there is really no concern at all. Just be careful of what you're doing to make sure it matches your intent.
Operations that care about signedness (ie they have distinct signed and unsigned forms with different semantics) are:
right shift
division (unsigned form not available in Java)
modulo (unsigned form not available in Java)
comparisons (except equality) (unsigned forms not available in Java)
Operations that don't care about signedness are:
and
or
xor
addition
subtraction
two's complement negation (-x means ~x + 1)
one's complement (~x means -x - 1)
left shift
multiplication
How can I declare an unsigned short value in Java?
You can't, really. Java doesn't have any unsigned data types, except char.
Admittedly you could use char - it's a 16-bit unsigned type - but that would be horrible in my view, as char is clearly meant to be for text: when code uses char, I expect it to be using it for UTF-16 code units representing text that's interesting to the program, not arbitrary unsigned 16-bit integers with no relationship to text.
If you really need a value with exactly 16 bits:
Solution 1: Use the available signed short and stop worrying about the sign, unless you need to do comparison (<, <=, >, >=) or division (/, %, >>) operations. See this answer for how to handle signed numbers as if they were unsigned.
Solution 2 (where solution 1 doesn't apply): Use the lower 16 bits of int and remove the higher bits with & 0xffff where necessary.
This is a really stale thread, but for the benefit of anyone coming after. The char is a numeric type. It supports all of the mathematical operators, bit operations, etc. It is an unsigned 16.
We process signals recorded by custom embedded hardware so we handle a lot of unsigned 16 from the A-D's. We have been using chars all over the place for years and have never had any problems.
You can use a char, as it is an unsigned 16 bit value (though technically it is a unicode character so could potnetially change to be a 24 bit value in the future)... the other alternative is to use an int and make sure it is within range.
Don't use a char - use an int :-)
And here is a link discussing Java and the lack of unsigned.
From DataInputStream.java
public final int readUnsignedShort() throws IOException {
int ch1 = in.read();
int ch2 = in.read();
if ((ch1 | ch2) < 0)
throw new EOFException();
return (ch1 << 8) + (ch2 << 0);
}
It is not possible to declare a type unsigned short, but in my case, I needed to get the unsigned number to use it in a for loop. There is the method toUnsignedInt in the class Short that returns "the argument converted to int by an unsigned conversion":
short signedValue = -4767;
System.out.println(signedValue ); // prints -4767
int unsignedValue = Short.toUnsignedInt(signedValue);
System.out.println(unsingedValue); // prints 60769
Similar methods exist for Integer and Long:
Integer.toUnsignedLong
Long.toUnsignedString : In this case it ends up in a String because there isn't a bigger numeric type.
No such type in java
Yep no such thing if you want to use the value in code vs. bit operations.
"In Java SE 8 and later, you can use the int data type to represent an unsigned 32-bit integer, which has a minimum value of 0 and a maximum value of 232-1." However this only applies to int and long but not short :(
If using a third party library is an option, there is jOOU (a spin off library from jOOQ), which offers wrapper types for unsigned integer numbers in Java. That's not exactly the same thing as having primitive type (and thus byte code) support for unsigned types, but perhaps it's still good enough for your use-case.
import static org.joou.Unsigned.*;
// and then...
UShort s = ushort(1);
(Disclaimer: I work for the company behind these libraries)
No, really there is no such method, java is a high-level language. That's why Java doesn't have any unsigned data types.
He said he wanted to create a multi-dimensional short array. Yet no one suggested bitwise operators? From what I read you want to use 16 bit integers over 32 bit integers to save memory?
So firstly to begin 10,000 x 10,000 short values is 1,600,000,000 bits, 200,000,000 bytes, 200,000 kilobytes, 200 megabytes.
If you need something with 200MB of memory consumption you may want to redesign this idea. I also do not believe that will even compile let alone run. You should never initialize large arrays like that if anything utilize 2 features called On Demand Loading and Data Caching. Essentially on demand loading refers to the idea to only load data as it is needed. Then data caching does the same thing, but utilizes a custom frame work for delete old memory and adding new information as needed. This one is tricky to have GOOD speed performance. There are other things you can do, but those two are my favorite when done right.
Alright back to what I was saying about bitwise operators.
So a 32bit integer or in Java "int". You can store what are called "bits" to this so let's say you had 32 Boolean values which in Java all values take up 32 bits (except long) or for arrays they take up 8 for byte, 16 for short, and 32 for int. So unless you have arrays you don't get any memory benefits from using a byte or short. This does not mean you shouldn't use it as its a way to ensure you and others know the data range this value should have.
Now as I was saying you could effectively store 32 Booleans into a single integer by doing the following:
int many_booleans = -1; //All are true;
int many_booleans = 0; //All are false;
int many_booleans = 1 | 2 | 8; //Bits 1, 2, and 4 are true the rest are false;
So now a short consists of 16 bits so 16 + 16 = 32 which fits PERFECTLY within a 32bit integer. So every int value can consist of 2 short values.
int two_shorts = value | (value2 << 16);
So what the above is doing is value is something between -32768 and 32767 or as an unsigned value 0 - 65535. So let's say value equaled -1 so as an unsigned value it was 65535. This would mean bits 1 through 16 are turned on, but when actually performing the math consider the range 0 - 15.
So we need to then activate bits 17 - 32. So we must begin at something larger than 15 bits. So we begin at 16 bits. So by taking value2 and multiplying it by 65536 which is what "<< 16" does. We now would have let's say value2 equaled 3 it would be OR'd 3x65536 = 196608. So our integer value would equal 262143.
int assumed_value = 262143;
so let's say we want to retrieve the two 16bit integer values.
short value1 = (short)(assumed_value & 0xFFFF); //-1
short value2 = (short)(assumed_value >> 16); //=3
Also basically think of bitwise operators as powers of 2. That is all they really are. Never look at it terms of 0's and 1's. I mostly posted this to assist anyone who may come across this searching for unsigned short or even possibly multi-dimensional arrays. If there are any typo's I apologize quickly wrote this up.
Java does not have unsigned types. What do you need it for?
Java does have the 'byte' data type, however.
You can code yourself up a ShortUnsigned class and define methods for those operators you want. You won't be able to overload + and - and the others on them, nor have implicit type conversion with other primitive or numeric object types, alas.
Like some of the other answerers, I wonder why you have this pressing need for unsigned short that no other data type will fill.
Simple program to show why unsigned numbers are needed:
package shifttest;
public class ShiftTest{
public static void main(String[] args){
short test = -15000;
System.out.format ("0x%04X 0x%04X 0x%04X 0x%04X 0x%04X\n",
test, test>>1, test>>2, test>>3, test>>4);
}
}
results:
0xC568 0xFFFFE2B4 0xFFFFF15A 0xFFFFF8AD 0xFFFFFC56
Now for those that are not system types:
JAVA does an arithmetic shift because the operand is signed, however, there are cases where a logical shift would be appropriate but JAVA (Sun in particular), deemed it unnecessary, too bad for us on their short sightedness. Shift, And, Or, and Exclusive Or are limited tools when all you have are signed longer numbers. This is a particular problem when interfacing to hardware devices that talk "REAL" computer bits that are 16 bits or more. "char" is not guaranteed to work (it is two bytes wide now) but in several eastern gif based languages such as Chinese, Korean, and Japanese, require at least 3 bytes. I am not acquainted with the number need for sandscript style languages. The number of bytes does not depend on the programmer rather the standards committee for JAVA. So basing char as 16 bits has a downstream risk. To safely implement unsigned shorts JAVA, as special class is the best solution based on the aforementioned ambiguities. The downside of the class is the inability of overloading the mathematical operations for this special class. Many of the contributors for this thread of accurately pointed out these issues but my contribution is a working code example and my experience with 3 byte gifs languages in C++ under Linux.
//вот метод для получения аналога unsigned short
public static int getShortU(byte [] arr, int i ) throws Exception
{
try
{
byte [] b = new byte[2];
b[1] = arr[i];
b[0] = arr[i+1];
int k = ByteBuffer.wrap(b).getShort();
//if this:
//int k = ((int)b[0] << 8) + ((int)b[1] << 0);
//65536 = 2**16
if ( k <0) k = 65536+ k;
return k;
}
catch(Throwable t)
{
throw new Exception ("from getShort: i=" + i);
}
}