Unsigned short in Java
Asked Answered
M

16

73

How can I declare an unsigned short value in Java?

Mailand answered 3/12, 2009 at 17:17 Comment(9)
Related question, if you're interested in the motivation behind this: "Why doesn't Java support unsigned ints?" stackoverflow.com/questions/430346Ligula
@ PP: If you want a language with the strengths of Java and C++ I can recommend Scala. It's really good at letting you go wild with types.Mogador
use a signed short. all the appropriate bit operations have variations which treat the value as unsigned.Wife
@Peter, for the most part signed math is adequate. But when you want to start manipulating bits unsigned has always been the safest way due to different implementations of signed math. It's like not carrying the tools to change your car's tyre. It's fine for most people almost all of the time. But when the time comes you really really want it!Burgee
@Heinzi, if you code OpenFlow controller the network devices send messages as unsigned integer values and as such those cases are handled gracefully in C/C++ based controllers, while Beacon Controller (Java based) for instance, get away with this by manually performing bit operations on it to get back the unsigned value, which is clearly a pain in the ***. I think they should introduce unsigned data types in Java 8Impair
@PP Bit operations are well-defined for signed values in Java.Forespeak
I stumbled upon this question because I needed an unsigned short for port operations: the largest possible port is 65535, which is 'coincidentally' the largest possible value of 2 bytes, i.e. a short.Zenobiazeolite
I think the whole point of Java is that you're not supposed to care about this stuff. If you need the numbers from 32,000 to 65,000 just use an int. If this stuff really matters to you, use C++.Cari
@Cari This stuff really mattered, as the code received to enrich was already built and I was a part of team where the management decision was to use Java. This is something so trivial and its so easy just saying ok don't use it, use something else..Mailand
O
81

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.

Oster answered 3/12, 2009 at 17:19 Comment(11)
@Jon: There seems to be no way in Java to have a normal machine‐level byte, meaning an 8‑bit location that can hold values [0–255] instead of [ −128 – +127 ]. I can’t believe they make us use signed bytes, when all you have to do in C is say unsigned char. Once you start down the road of signed datatypes only, it screws up all your unsigned bitmaps. Really quite unpleasant. The Java designers thought they were simplifying things to make them less error‐prone, but once again all they managed to do was make them a lot harder and more error‐prone than before. There’s a lot of that in Java.Ectoplasm
@Jon: OTOH, since Java's char is unusable for Unicode codepoints, you can just as well use it for unsigned shorts: it won't be any more horrible than any existing code using char when they really should use int.Cuccuckold
@ninjalj, Oh where are you typedef?Corporeal
@Ectoplasm - well FWIW it's not really accurate to imply that the "machine level" byte is 0-255 and not -128-+127. Machine bytes are just that - 8 bits, and the interpretation of the value may depend on the instruction used. In many cases whether you mentally treat a byte as signed or unsigned actually makes no difference to the assembly (e.g., addition, subtraction, some multiplication, all bit operations). The signed interpretation shouldn't matter for most bitmap use - all the bitwise operators operate as expected. It's only really sign extension on conversion you need to watch out for.Njord
What, exactly, makes char horrible? This is FUD rather than help.Corruptible
@AleksandrDubinsky: There's nothing wrong with char as a type - but using it as an unsigned 16 bit integer rather than text is an abuse of the type, IMO. When I see char in code, I think "UTF-16 code unit", not "arbitrary 16-bit integer".Oster
@JonSkeet It would be better to bring up concrete reasons other than style before throwing out words like "horrible." What would be helpful to future visitors is if you repeated the contents of this answer #398367 in order to explain how to use unsigned data types in Java. In Java 8, the class Integer exposed some of these techniques as methods toUnsignedLong, compareUnsigned, divideUnsigned, etc, however there is value in a full documentation especially since class Short did not expose these methods.Corruptible
@AleksandrDubinsky: I've added my reasoning to the answer, but kept "horrible" in there as I believe it is horrible. I'm not going to start repeating the content of other answers in a nearly-8-year-old answer.Oster
@JonSkeet This page, and this answer, gets a lot of views. Of course, you're under no obligation to help the community.Corruptible
@AleksandrDubinsky: How very passive-aggressive of you. I think we're done here. If anyone wants to follow your link, they can see the content to the other answer there.Oster
@AleksandrDubinsky: Flagged. I'm done here. The idea that I "only work for points" is offensive and blatantly not the case.Oster
F
17

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.

Forespeak answered 3/12, 2009 at 18:20 Comment(1)
sBuff.append( new Integer(iArray[i++] & 0xffff) + ","); thank you!Pretrice
I
15

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.

Ingraham answered 17/5, 2012 at 15:1 Comment(0)
V
11

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.

Viticulture answered 3/12, 2009 at 17:19 Comment(2)
char is defined to be 16 bits, not a Unicode character (whatever that means), always and forever. If char changed to 24 bits, it would no longer be Java.Delk
I don't think it'll ever change either. The reason why 16 bits is to support unicode (from the JLS: "The Java platform tracks the Unicode specification as it evolves." and "The Unicode standard was originally designed as a fixed-width 16-bit character encoding") and from java.lang.Character: "The methods that only accept a char value cannot support supplementary characters" - so origianlly char was 16 bit because that was how wide unicode was. Now unicode is larger and char can no longer represent all unicode characters.Viticulture
S
5

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);
}
Sphygmomanometer answered 20/10, 2014 at 20:54 Comment(0)
E
4

No such type in java

Evangelist answered 3/12, 2009 at 17:18 Comment(0)
R
4

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.

Ragen answered 1/3, 2021 at 19:58 Comment(0)
W
2

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)

Wheelsman answered 15/12, 2017 at 10:28 Comment(0)
F
1

Yep no such thing if you want to use the value in code vs. bit operations.

Furfur answered 3/12, 2009 at 17:19 Comment(0)
A
0

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.

Assumpsit answered 3/2, 2014 at 16:16 Comment(0)
H
0

No, really there is no such method, java is a high-level language. That's why Java doesn't have any unsigned data types.

Heisser answered 8/8, 2018 at 10:40 Comment(0)
T
-1

Java does not have unsigned types. What do you need it for?

Java does have the 'byte' data type, however.

Telegu answered 3/12, 2009 at 17:19 Comment(5)
byte is 8 bit, short is 16 bit... don't think byte will work :-)Viticulture
i would like to build a multi-dimensional array with for example 10000*10000 entries of short numbers... thats why i thought of unsigned shorts, for allocating less memoryMailand
Thanks for the correction, TofuBeer. Too quick on the draw, I guess.Telegu
Makes sense, @maiky. Also, if you're worried about memory, you could probably lift the tricks from sparse matrices if you anticipate a lot of entries in your array will be zero.Telegu
Byte in java is also signed for some strange reason.Pillsbury
M
-1

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.

Mogador answered 3/12, 2009 at 17:56 Comment(0)
H
-1

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.

Halfmoon answered 1/10, 2013 at 20:48 Comment(2)
You can use, System.out.format ("0x%04X 0x%04X 0x%04X 0x%04X 0x%04X\n", test, test & 0xffff >> 1, test & 0xffff >> 2, test & 0xffff >> 3, test & 0xffff >> 4);. This will give you an unsigned shift of short. However this adds 1 operation (bitwise &) to each shit.Acaleph
Java has a logical right shift operator, >>>. Also, char will never change its size.Corruptible
R
-2
//вот метод для получения аналога 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);
      }
    }
Reinold answered 11/12, 2018 at 19:10 Comment(1)
Hey there, welcome to Stack Overflow. This answer may be correct, but it could be improved in a couple ways: 1.) it would help if you explained what's going on in the code. How does the code solve the OP's problem? and 2.) since this is a fairly old question, what does your answer add that the existing answers don't already have?Saharan

© 2022 - 2024 — McMap. All rights reserved.