Why does byte representation in Java store data in decimal? - java

I was debugging a problem where I created a byte array from binary representation of strings such as below.
While debugging the array just to see how it is stored, I could see them stored internally as decimals. Why is that?
When it gets interpreted as bytecode I am assuming it will get converted as binary. Then why not store in binary in the first place.
String[] binArray = {"10101","11100","11010","00101"};
byte[]bytes = new byte[binArray.length];
for (int i=0; i< binArray.length;i++){
bytes[i] = Byte.parseByte(binArray[i],2);
}
I may be missing something here. Hence request your guidance.

There seems to be a very general misunderstanding.
In some sense, all data is stored "in binary form". Particularly, the integral numerical values, like byte, short, int etc., are internally all stored in binary form. This internal representation is known as the Two's complement form.
(For floating point numbers, the representation is a bit more complicated: It's the IEEE 754 representation - still, they are stored in binary form)
The key issue that has likely lead to your question is: When you just print a number, or convert them to a string, with
System.out.println(someByte);
or
String s = String.valueOf(someByte);
then by default, the decimal form is printed. Mainly because this is the most "natural" and most readable form for humans.
You can pass your bytes to Integer.html#toBinaryString to create the string representation of their binary representation:
System.out.println(Integer.toBinaryString(someByte));

Well, the JVM, just like any program doesn't store numeric values as "decimal" or "hexadecimal". It's just a bit-pattern in memory. Your debugger displays the value in decimal format. This is just for convenience, since most people prefer decimal to binary format for readability. For the computer itself it's just a bit-string of 8 bits length, stored as binary-value.

While debugging the array just to see how it is stored, I could see them stored internally as decimals. Why is that?
You are seeing the byte value displayed in decimal. The debugger is not displaying the internal value.
When it gets interpreted as bytecode I am assuming it will get converted as binary. Then why not store in binary in the first place.
It is stored in binary.

Related

Why is Binary represented as a String?

So I am quite new to Java and motivated to learn. This question might seem simple but I genuinely don't understand and have searched Google for answers (no luck).
I am converting a decimal into Binary in Java. However, I thought representations of numbers are supposed to be given in data types int, double, and etc.
The code is as follows :
int decimal = 99;
String binary = Integer.toBinaryString(decimal);
System.out.println(binary);
Why is it String binary, should it not be any of the numerical data types?
Internally, all values are stored as binary values. Because it's easier to read, integers are converted into digits for display. Displaying a value as a binary is thus purely a representation issue.
So 99 is internally stored as 01100011. You can display it as a hexadecimal (0x63), a decimal (99), or a binary. But because the numerical value is the same in each case, the only difference is the symbols used to display it, and this symbolic representation is as a String.
The following ints are all equal:
int i = 99;
int j = 0o143;
int k = 0x63;
int l = 0b1100011;
If you want to print them, you have to convert them to a String using a utility method of Integer, or you use number formatting.

Representing relative addressing in byte code using Java

I'm trying to represent relative addressing mode in Java. As we know, with relative addressing the operand must take a value between -128 and +127, as relative addressing uses 2's complement to represent whether the operand should be added or subtracted from the base value.
However I'm struggling to convert this into its hexadecimal representation.
2's complement form uses the most significant bit to determine whether the bit pattern in question is positive or negative, hence the reason for the range of -128 to +127.
Let's say we have the relative address operand *+3A, which states that the user wants to add 3A to the value held in the program counter. This is simple enough as 3A converts to 00111010 binary.
But then how do I go about representing *-3A in Java? If I convert 3A to decimal, which is 58 and then negate it to get -58 and then convert that back to hexadecimal, will that work?
I'm not sure if this is just something that's really simple and I'm making it into something bigger than it actually is.
We have a couple things going on.
Two's Complement is the representation for negative integers in all modern machines. To negate an integer, you:
take the bitwise complement, and then
add one, ignoring the carry-bit.
So this needs to be done in the context of a specific word-size. If your allowable range is -128 to 127, you are dealing with an 8-bit "word".
The second issue is how you encode the result for human (or compiler) consumption. In either case, simply using a signed decimal integer is probably ideal.

Rounding error from BigDecimal to byte array in Java

How should one properly handle a conversion rounding error with BigDecimal in Java:
BigDecimal -> byte[] -> BigDecimal
I have a custom datatype 32 bytes in length (yep, 32 bytes not 32 bits) and I need to decode the fractional part of BigDecimal into byte[].
I understand that I will lose some accuracy. Are there any established techniques to implement such a conversion?
NOTE:
It is fixed point datatype of form MxN, where M % 8 == N % 8 == 0
Your fixed-point fractional part can be interpreted as the numerator, n, of a fraction n/(2256). I suggest, therefore, computing the BigDecimal value representing 1/(2256) (this is exactly representable as a BigDecimal) and storing a reference to it in a final static field.
To convert to a byte[], then, use the two-arg version of BigDecimal.divideToIntegralValue() to divide the fractional part of your starting number by 1/(2256), using the MathContext argument to specify the rounding mode you want. Presumably you want either RoundingMode.HALF_EVEN or RoundingMode.HALF_UP. Then get the BigInteger unscaled value of the result (which should be numerically equal to the scaled value, since an integral value should have scale 0) via BigDecimal.unscaledValue(). BigInteger.toByteArray() will then give you a byte[] closely related to what you're after.*
To go the other way, you can pretty much reverse the process. BigDecimal has a constructor that accepts a byte[] that, again, is very closely related to your representation. Using that constructor, convert your byte[] to a BigInteger, and thence to BigDecimal via the appropriate constructor. Multiply by that stored 1/(2256) value to get the fractional part you want.
* The biggest trick here may involve twiddling signs appropriately. If your BigDecimals may be negative, then you probably want to first obtain their absolute values before converting to byte[]. More importantly, the byte[]s produced and consumed by BigInteger use a two's complement representation (i.e. with a sign bit), whereas I suppose you'll want an unsigned, pure binary representation. That mainly means that you'll need to allow for an extra bit -- and therefore a whole extra byte -- when you convert. Be also aware of byte order; check the docs of BigInteger for the byte order it uses, and adjust as appropriate.

Why is a double always 8 bytes and an int always 4 bytes, even if the int has more digits?

I don't understand how an int 63823, takes up less space than a double 1.0. Is there not more information stored in the int, in this particular instance?
I don't understand how an int 63823, takes up less space than a double 1.0. Is there not more information stored in the int, in this particular instance?
Good question. What you're seeing when you see 63823 and 1.0 is a representation of the underlying data, you are not seeing the underlying data. It is specially formatted so that you can read it, but it is not how the machine sees it.
Java uses very special formats for representing int and double. You need to look at those representations to understand why 63823 takes thirty-two bits when represented as a Java int and 1.0 takes sixty-four bits when represented as a Java double.
In particular, 63823 as an int in Java is represented as:
00000000000000001111100101001111
and 1.0 as a double is represented in Java as:
0011111111110000000000000000000000000000000000000000000000000000
If you want to explore more, I recommend Two's Complement and What Every Computer Scientist Should Know About Floating-Point Arithmetic.
Not exactly. The double 1.0 represents more information because, by the definition of a double as a 64 bit float, there are more values that it could be. To use your example, if you had a special data type that could only have two values, 63823 and 98321234213474932, then it would only take 1 bit to represent the number 63823, though it would be far less useful than an int.
In terms of implementation, it's often a lot easier and faster to work with fixed-size data types, so that you can allocate a fixed chunk of memory (that's what a variable is) without having to know it's value and constantly reallocate space. Examples of a variables with a different approach would be String and BigInteger, which do allocate space to accommodate their values. Note that both are immutable in Java -- that's not a coincidence.
These primitive datatypes need to be defined somewhere for you to use them. It is not a flexible container where you can stuff in whatever you want, rather more like a bottle which takes the same space no matter if full or empty. And they also have a maximum they can contain.
Read more yourself here.
The zeros that are not shown also count. Approximately, ignoring the fact that the numbers are actually stored in binary and not in decimal, when you write both numbers with the implied zero digits included, you get:
1.0 = 1.00000000000000000*10^0000
63823 = 0000063823
As you can see, 1.0 is twice as long as 63823. Therefore it requires twice as much storage.
The int and double don't have decimal digits at all. The decimal representation of the int has 8 decimal digits after removing leading zeros. The int itself has room for 32 binary digits. The double has room for 53 binary digits in the mantissa and a 10-bit exponent, and a sign bit.

How to convert numbers stored as two character ASCII strings to binary?

I have numbers written as ASCII codes each of 2 bytes which wastes a lot of the space. I want to convert those number to their corresponding ASCII code to save the space.
Any idea?
If you mean characters, Java uses two bytes per character as part of its Unicode support. If you give ASCII values, Java will make the upper byte zero. You won't save a thing.
If you mean floats or doubles or ints, the bytes per value are fixed there as well.
You're barking up the wrong tree. I don't think this will save you anything no matter what you do.
You're better off writing C or C++ if you need that kind of optimization, not Java.
My first thought is that this is an imagined optimization that isn't supported by data. The only application that would justify something like this would be scientific computing on a large scale. Even that wouldn't justify it, because you'll need more precision than a byte per value.
You can use the parse methods on the default types' class. For example, if these numbers are integers and are stored as string "34", you can use Integer.parseInt("34") which returns you a single int whose value is 34. Similarly for Double, Float and Long.
Do you want to convert the Hex number to bytes? If so, this is your answer:
Convert a string representation of a hex dump to a byte array using Java?
If you want to convert number to byte -> http://snippets.dzone.com/posts/show/93
Convert the two digit ASCII string to a byte. When you need the ASCII back just convert it to a string. The following code shows how to do this for "95".
public class Main {
public static void main(String[] args) {
byte b = Byte.parseByte("95");
String bString = "" + b;
}
}
If you need to change the way they are stored in a file, just read the two digit text numbers in as strings and write them out to another file as bytes.

Categories