Java - derby - unsigned int - java

I would like that one of my columns in a specific table would not get negative numbers.
Is there a way to declare an unsigned int in derby DB ?

Q: Is there a way to declare a column "unsigned int" in a Derby DB table?
A: I believe answer is "No":
http://db.apache.org/derby/docs/10.0/manuals/reference/sqlj124.html
http://db.apache.org/derby/docs/10.0/manuals/reference/sqlj124.html
... HOWEVER ...
You should easily be able to "CAST" the stored value in any query:

The answer is no. Java (unfortunately) has no support for unsigned arithmetics.
But you can still use Java's int and make your own methods to do unsigned arithmetic, like this. Even better is to create an UnsignedInteger class and let it handle all that arithmetic.
I don't know if it's worth it though. You can just use long as jtahlborn suggests.

Java does NOT support the type unsigned int, as opposed to C or C++.
On the other hand, there is a simple way to circumvent this limitation by using:
An intermediate long variable/literal
A cast to (int)
First, let us note that both signed and unsigned int have the same number of bits; they are both 32 bits in size.
The main difference is, that for signed integers the MSB (Most Significant Bit) or bit 0 is used to indicate that the actual integer is negative or positive.
If this bit is set to 1 the integer is negative, if it is set to 0, the integer is negative. So, you will end up with 31 bits for the value of the integer, and 1 bit for the sign.
For unsigned integers, all the 32 bits are used to represent the value of the integer. You can now have larger numbers.
The signed integers range from -2^31 to (2^31 - 1)
The unsigned integers range from 0 to (2^32 - 1)
To show the size limitation issue, try to compile the following snippet:
public static void main (String[] args){
int i = 2_147_483_648;//This line will generate a compiler error
}
}
The compiler will complain saying integer number too large.
Let us see how we can circumvent this and still store this number in a Java integer, and retrieve it back.
The idea behind the proposed solution stems from the fact that a series of bits is interpreted to mean something. It could be a representation of an image, a Java object, a C struct, a character, etc.
You "interpret" the series of bits based on what you "expect" that series of bits to represent. If you are expecting a character, you might be looking to match the series against an ASCII table. If you are expecting an image, you might be looking to decode a JPEG.
Now, and coming back to integers, if you are looking for signed integers you will interpret the MSB as the sign bit. If you are looking for unsigned integers you will interpret the MSB as part of the value.
To give an example, let us assume that you have the following series of 32 bits:
in hex 0x8000_0000 or in binary 0b1000_0000_0000_0000_0000_0000_0000_0000
The MSB is set to 1 all other bits are 0.
If you are looking for/expecting a signed integer these 32 bits would be interpreted as the representation of the negative decimal number -2_147_483_648
If you are looking for/expecting an unsigned integer these same 32 bits would be interpreted as the representation of the positive decimal number 2_147_483_648
Hence, the solution would be to store the values in a signed 32-bit integer and interpret them as an unsigned 32-bit integer.
Here is how we will modify the previous snippet and save 2_147_483_648 into an integer value and be able to print it correctly.
To do so, we will:
First, use a long intermediate datatype/value
Then cast that value to int to save it
Finally, mask/ignore & the extra bits and display it
public static void main (String[] args){
//1. cast a 64-bit long value that fits into a 32-bit int
int i = (int)2_147_483_648L;
//2. Mask the extra long bits
System.out.println(i & 0x0000_0000_FFFF_FFFFL);
}
}
The long variable can hold 64 bits, and its MSB, or sign bit, is not affected by its first 32 bits. You will notice a bitwise operation happening here:
i & 0x0000_0000_FFFF_FFFFL
This is telling the compiler to ignore, or mask, all the bits that are beyond the first 32 bits we are interested in. Our integer is 32-bit.
If you want to do some arithmetic operation on the int value before saving it, you could resort again to a long intermediate variable.
Here is how, and this will be the proposed solution:
public static void main (String[] args){
int i = (int)2_147_483_648L;
int j = 1_000_000;
long tempL = i + j;//Use a temp long to perform the operations
i = (int)tempL; //We save back into i and store in a DB for example
//Now we use the saved value to display it, for example
System.out.println(i & 0x0000_0000_FFFF_FFFFL);
}
}
Good luck and hope the above helps!

Related

Assign negative int to long in java

I've 2 integer values stored in a bytebuffer, in little-endian format. These integers are actually the 32-bit pieces of a long. I've to store them as a class' member variables, loBits and hiBits.
This is what I did:
long loBits = buffer.getInt(offset);
long hiBits = buffer.getInt(offset + Integer.BYTES);
I want to know why directly assigning signed int to long is wrong. I kind of know what's going on, but would really appreciate an explanation.
The int I read from the buffer is signed (because Java). If it is negative then directly assigning it to a long value (or casting it like (long)) would change all the higher order bits in the long to the signed bit value.
For e.g. Hex representation of an int, -1684168480 is 9b9da0e0. If I assign this int to a long, all higher order 32 bits would become F.
int negativeIntValue = -1684168480;
long val1 = negativeIntValue;
long val2 = (long) negativeIntValue;
Hex representation of:
negativeIntValue is 0x9b9da0e0
val1 is 0xffffffff9b9da0e0
val2 is 0xffffffff9b9da0e0
However, if I mask the negativeIntValue with 0x00000000FFFFFFFFL, I get a long which has the same hex representation as negativeIntValue and a positive long value of 2610798816.
So my questions are:
Is my understanding correct?
Why does this happen?
Yes, your understanding is correct (at least if I understood your understanding correctly).
The reason this happens is because (most) computers use 2's complement to store signed values. So when assigning a smaller datatype to a larger one, the value is sign extended meaning that the excess part of the datatype is filled with 0 or 1 bits depending on whether the original value was positive or negative.
Also related is the difference between >> and >>> operators in Java. The first one performs sign extending (keeping negative values negative) the second one does not (shifting a negative value makes it positive).
The reason for this is that negative values are stored as two's complement.
Why do we use two's complement?
In a fixed width numbering system what happens, if you substract 1 from 0?
0000b - 0001b -> 1111b
and what is the next lesser number to 0? It is -1.
Therfore we thread a binary number with all bits set (for a signed datatype) as -1
The big advantage is that the CPU does not need to do any special operation when changing from positive to negative numbers. It handles 5 - 3 the same as 3 - 5

Why am I getting a value back from Long.parseUnsignedLong when I shouldn't be

When I do
Long.parseUnsignedLong("FBD626CC4961A4FC", 16)
I get back -300009666327239428
Which seems wrong, since the meaning of unsigned long according to this answer https://stackoverflow.com/a/2550367/1754020 is that the range is always positive.
To get the correct number from this HEX value I do
BigInteger value = new BigInteger("FBD626CC4961A4FC", 16);
When I print value it prints the correct value. but if I do value.longValue()
again I get the same -300009666327239428 is this of the number being too big and overflowing ?
Java 8 does (somewhat) support unsigned longs, however, you can't just print them directly. Doing so will give you the result that you saw.
If you have an unsigned long
Long number = Long.parseUnsignedLong("FBD626CC4961A4FC", 16);
you can get the correct string representation with the function
String numberToPrint = Long.toUnsignedString(number);
If you now print numberToPrint you get
18146734407382312188
To be more exact, your number is still going to be a regular signed long which is why it shows overflow if printed directly. However, there are new static functions that will treat the value as if it was unsigned, such as this Long.toUnsignedString(long x) or Long.compareUnsigned(long x, long y).
The hexadecimal number "FBD626CC4961A4FC", converted to decimal, is exactly 18146734407382312188. That number is indeed larger than the maximum possible long, defined as Long.MAX_VALUE and which is equal to 263-1, or 9223372036854775807:
System.out.println(new BigInteger("FBD626CC4961A4FC", 16)); // 18146734407382312188
System.out.println(Long.MAX_VALUE); // 9223372036854775807
As such, it's normal that you get back a negative number.
You do not have an exception, as it is exactly the purpose of those new *Unsigned* methods added in Java 8, to give the ability to handle unsigned longs (like compareUnsigned or divideUnsigned). Since the type long in Java is still unsigned, those methods work by understanding negative values as values greater than MAX_VALUE: it simulates an unsigned long. parseUnsignedLong says:
An unsigned integer maps the values usually associated with negative numbers to positive numbers larger than MAX_VALUE.
If you print a long that was the result of parseUnsignedLong, and it is negative, all it means is that the value is greater than the max long value as defined by the language, but that methods taking unsigned longs as parameter will correctly interpret those values, as if they were greater than the max value. As such, instead of printing it directly, if you pass that number to toUnsignedString, you'll get the right output, like shown in this other answer. Not all of these methods are new to Java 8, for example toHexString also interprets the given long as an unsigned long in base 16, and printing Long.toHexString(Long.parseUnsignedLong("FBD626CC4961A4FC", 16)) will give you back the right hex String.
parseUnsignedLong will throw an exception only when the value cannot be represented as an unsigned long, i.e. not a number at all, or greater than 264-1 (and not 263-1 which is the maximum value for a signed long).
Yes, it overflows when you are trying to print it, as it is converted to Java long type. To understand why let's take log2 of your dec value.
First thing, original value is 18146734407382312188. It's log2 is ~63.9763437545.
Second, look into documentation: in java long type represents values of -2^63 and a maximum value of 2^63-1.
So, your value is obviously greater then 2^63-1, hence it overflows:
-2^63 + (18146734407382312188 - 2^63 + 1) = -300009666327239428
But as #Keiwan brilliantly mentioned, you still can print proper value using Long.toUnsignedString(number);
Internally unsigned and signed numbers are represented in the same way, i.e. as 8 bytes in case of a long. The difference only how the "sign" bit interpreted, i.e. if you'd do the same in a C/C++ program and store your value into an uint64_t then cast/map it to a asigned int64_t you should get the same result.
Since the maximum value 8 bytes or 64 bits can hold is 2^64-1 that's the hard constraint for such numbers. Also Java doesn't directly support unsigned numbers and thus the only way to store an unsigned long in a long is to allow for a value that's higher than the signed Long.MAX_VALUE. In fact Java doesn't know whether the string/hexcode you're reading is meant to represent a signed or unsigned long so it's up to you to provide that interpretation, either by converting back to a string or using a larger datatype such as BigInteger.

Why are these two different representations (dec vs. hex) of integers different in Java?

Say I have two integers, one in decimal the other in hexadecimal:
int myInt01 = 0xc7d23020;
int myInt02 = 3352440864;
The are both the same number, but when I try to assign the decimal integer to a variable in Java, I get the error:
error: integer number too large: 3352440864
But when I assign the hexadecimal integer to a variable in Java, everything works as it should.
Why is it this way?
That's because 0xc7d23020 is interpreted as -942526432 which is a valid int value, while 3352440864 is clearly a wrong int value because it's higher than the limit 2147483647;
I guess this is intended behavior: The binary representation of this number has the most significant bit set, in a 32 bit datatype. Since in Java int is a signed datatype, the most significant bit is reserved for the sign of the number. Thus, the number is not a valid positive number. This is what the compiler is telling you. However, since it is a valid negative integer, it does not complain when you assign it using the hex-representation.
You can try assigning a number that would need more than 32 bits to an integer variable using the hex-representation. This will lead to a compiler error.
The max value that a int variable can hold is 2147483647. That's why it is giving that error. You can check that out yourself by doing this: System.out.println(Integer.MAX_VALUE);
To find out the minimum value that a int variable can hold System.out.println(Integer.MIN_VALUE);

How to read unsigned values from files

I am trying to read binary data (Doom WAD files), which contain a lot of unsigned short and unsigned byte values.
At the moment I read the file into a byte[], wrap a ByteBuffer with little-endian order around it and access the values by bbuf.getShort() etc. respectively.
Converting those e. g. to 2D-coordinates is not a problem, because in the end it won't matter if they range eg. from -128 to 128 or from 0 to 256, but more often the short values are used as array indices and short/byte values as flags/, so I need a fast way to treat them as signed types.
I know, Java doesn't have unsigned types "for sake of simplicity...".
Can you make any suggestions?
In order to save unsigned ints you need a long. Then you need to truncate last 32 bits. You can use following trick to do it.
final long UNSIGNED_INT_BITS = 0xffffffffL;
int a = -3;
long b = UNSIGNED_INT_BITS & a;
System.out.println(a);
System.out.println(b);
System.out.println(Long.toHexString(UNSIGNED_INT_BITS));
Output:
-3
4294967293
ffffffff
If all else fails, you could always store them internally as ints and make sure you do proper conversion when reading/writing.
(Read as byte/short, cast to int, add 2^bits if negative. Just truncate to 8/16 bits when writing.)
Hardly the most elegant solution, I admit.
If you need to interprete 0xFF byte as 256 do the following
int n = b & 0xFF;

Declaring an unsigned int in Java

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.

Categories