Let's start by saying that integral data types are those that represent only whole numbers. Each number will have a well defined successor. So floating point numbers are not integral data types (what comes after 0.1? 0.11 or 0.111?) but integers are.
That being said, Java supports the following integral data types:
long. On the other hand, C# supports
ulong. On purpose, I'm leaving outside of this conversation the
chardata type since, despite it can be considered an integral type, I don't want to confuse anyone by mixing characters with numbers. So a total of 4 types in Java and 8 types in C#.
The interesting part is the range of numbers that each one of these types supports. To calculate this range, let's first take a look to the size of each one of these types:
sbyte - 8 bits (1 Byte) byte - 8 bits (1 Byte) short - 16 bits (2 Bytes) ushort - 16 bits (2 Bytes) int - 32 bits (4 Bytes) uint - 32 bits (4 Bytes) long - 64 bits (8 Bytes) ulong - 64 bits (8 Bytes)This is true for both Java and C# (remember that only a subset of these types is supported in Java). Having these sizes, there's a simple formula to compute the range of each type. In the case of C# we'll also have to pay attention to the prefix (if any) of the type. This prefix can be "s" (
sbyte), "u" (
uint), or none (
long). This hints us whether the range is going to include negative numbers or not: "s" means "signed" so it will include negative numbers, "u" means "unsigned" so it will include only positive numbers, and when nothing is specified, assume negative numbers are included. So let's see the formula:
- If the number includes negative values, the lower bound is going to be - 2^(bits - 1).
- If the number includes negative values, the upper bound is going to be 2^(bits - 1) - 1.
- If no negative numbers are included, the lower bound is going to be 0.
- If no negative numbers are included, the upper bound is going to be 2^bits.
sbyte [-2^7 .. 2^7 - 1] = [-128 .. 127] byte (Java) [-2^7 .. 2^7 - 1] = [-128 .. 127] byte (C#) [0 .. 2^8] = [0 .. 255] short [-2^15 .. 2^15 - 1] = [-32,768 .. 32,767] ushort [0 .. 2^16] = [0 .. 65,535] int [-2^31 .. 2^31 - 1] = [-2,147,483,648 .. 2,147,483,647] uint [0 .. 2^32] = [0 .. 4,294,967,295] long [-2^63 .. 2^63 - 1] = [-9,223,372,036,854,775,808 .. 9,223,372,036,854,775,807] ulong [0 .. 2^64] = [0 .. 18,446,744,073,709,551,615]So here are some things to notice. First, if you use both C# and Java, be careful when you use the
bytedata type because it doesn't have the same range in both languages. An equivalent for the Java's
bytein C# is
sbyte. Second, note that in case of signed types, the upper bound is always 1 less than the lower bound (32,767 vs 32,768 for an
int). This is because the value 0 is always considered a positive number. Third, try to say the name of the number represented by a
longvalue. It will probably take you a while.
Another point that is usually misunderstood is the fact that the size of these data types is going to be always the same regardless of the architecture our program is running on. So you might be running your program in a 64 bit machine, but an
intis going to be always 32 bit long so it will have the same range. This is true for both C# and Java.
Finally, I would like to know why in hell the C# design team decided to break the pattern creating an
ubyterespectively. It doesn't make any sense to me unless they were really really drunk that night (or because any other obscure compatibility thing that I can't think of right now).