I'm trying to write a method in java that will take an input of any number of 0 or 1 digits and output that line after being encoded with Hamming Code.
I have managed to write the code when knowing the number of digits the input will have (in this case 16) because knowing the number of digits in the input, I immediately know the number of parity bits there have to be added (5 in this case) to a total of 21 digits in the final output. I am working with int arrays so I need to declare a size in the beginning and my code works based on those exact sizes.
Can you guys think of any way/algorithm that can give me the number of digits the output will have (after adding the relevant parity digits to the number of input digits) based solely on the number of input digits?
Or do I have to tackle this problem in a totally different way? Any suggestions? Thank you in advance!
Cheers!
From my understanding, you get your 6th parity bit at 32 bits of input, 7th at 64, etc. so what you need is floor(lg(n)) + 1, which in java you can get by using 32 - Integer.numberOfLeadingZeros(n).
Assuming your input is made up entirely of 0s and 1s, you would do
int parityDigits = 32 - Integer.numberOfLeadingZeros(input.length());
Is your input a String or individual bits? If you input as a String, you can convert each character to a bit, and the length of the String gives you the length of the array.
If you need to input the bits one at a time, store them in an ArrayList. When all bits have been entered, you can convert your list to an array easily, or use the size of the list etc.
Related
I'm not asking for a built-in class that accomplishes this, I'm just curious on how encoding works behind the scenes in java. For example, An integer in java can be stored in 4 bytes, between -2147483648 and 2147483647. Lets use 500 as the number for this demonstration. From what I understand, the computer initially stores this number in memory as 1F4 in hex, which is 00000000 00000000 00000001 11110100 in binary. When I looked up how ASCII works, it encodes each digit 0-9 to its corresponding ASCII value (0 translates to 048). However, how is the binary number stored in ram able to separate each digit so that each digit can be encoded to its corresponding ASCII value? We know that the number is 500, but this is just an abstraction. The computer just sees 1's and 0's. So how is the 5 mapped to 053, and both 0's mapped to 048 for this example. Does the jvm account for this automatically behind the scenes? Or am I misunderstanding how the entire process works. Thanks.
Well, IF I understand your question directly...
You could start by dividing your integer by 10 and getting the remainder -- the mod function in Java (%) is useful for this.
int digitInteger = originalNumber % 10;
The digitInteger variable now holds a number 0-9, the integer version of the ASCII (or Unicode, or whatever) of the last digit in the number. Unfortunately for your example, this will be a fairly boring 0.
Let us instead use the number 543 as our example, it will make things easier. If originalNumber was 543, then digitInteger will now be 3. Since 48 represents ASCII 0, then you can add that to digitInteger to get the ASCII equivalent. I'll leave it to you put that somewhere, since Java does not deal with ASCII as its default encoding. (Unicode, I believe, has the same values as ASCII for these digits).
Now you execute something like
originalNumber = originalNumber / 10;
This integer division will truncate the digit you just isolated, 3 in our case, and originalNumber is now 54.
You repeat this process - mod by 10 to isolate the last digit, convert to character, prepend to characters previously found, integer divide by 10 to truncate the last digit -- until originalNumber is 0 -- digitInteger, as you can probably see now, will be 4 on the next round and 5 on the round after that, and you prepend those to the 3 you got the first time to get your ASCII equivalent.
While converting a String into BigInteger, Java internally calculates the number of bits and then the number of words(each word is a group of 9 integers i think) in a BigInteger as can be seen here from Line 325 to Line 327. numWords is used then to create an array that can accomodate that BigInteger.
I don't understand the logic used for calculating numBits in line 325 and then the logic for numWords in Line 326.
Logically i think that for the string "123456789", numWords should be 1 and for "12345678912",numWords should be 2 , but that's not always the case. For example for "12345678912345678912", numWords should be 3, but it comes out to be 2.
Can anyone please explain the logic used in line 325 and 326?
To represent decimal number of numDigits as binary number, it requires
numDigits * Math.log(10) / Math.log(2)
bits.
int numBits = (int)(((numDigits * bitsPerDigit[radix]) >>> 10) + 1);
In the calculation above bitsPerDigit[10] is 3402.
Math.log(10) / Math.log(2) * Math.pow(2, 10) = 3401.6543691646593
In Java, BigIntegers are not stored as strings or bytes with a digit each. They are stored as an array of 32-bit integers, which together form the so-called magnitude of the BigInteger. There can be no leading zero integers(*), so the BigInteger is stored as compactly as possible.
The "words" mentioned are these 32-bit integers. They are not groups of 9 digits, they are used in full, so each bit counts.
So you just have to know how many 32-bit integers are stored, which is the length of the internal array times 32. But the top integer can still have leading zeroes, so you must get the number of leading zeroes of that top integer and subtract them from the obtained product, in pseudo-code:
numBits = internalArray.length * 32 - numberOfLeadingZeroBits(internalArray[0]);
Note that the internal array is stored with the top integer at the lowest address (I have no idea why that is), so the top integer is at index 0 of the array.
(*) In reality, the above is a little more complicated, since the top item may be stored at an offset from the start of the array (probably to make certain calculations easier), but to understand the mechanism, you can pretend there are no extra integers.
Words doesn't refer to words as you know it - it's referring to words as memory blocks.
https://en.wikipedia.org/wiki/Word_(computer_architecture)
I need to compress 20-40 char size of a numeric number to a 6 char size number. So far I have tried Huffman and some Zip algorithms but not getting the desired outcome.
Can some one please advise any other Algorithm/API for this work in Java?
Example:
Input: 98765432101234567890
Desired Output: 123456
Please note: I didn't mean the output has to come as 12345 for the given input. I only mean that if I specify 20 byte number, it should be compressed to a 6 byte number.
Usage: Compressed number will be feeded to a device (which can only take up-to-6 numeric chars). Device will decode the number back to the original number.
Assumption/Limits:
If required both client and device(server) can share some common
properties required for encoding/decoding the number.
Only one request can be made to a device i.e. all data should be fed
in one request, no chunk of small packets
Thanks.
This will be the best you can get assuming that any combination of digits is a legal input:
final String s = "98765432101234567890";
for (byte b : new BigInteger('0'+s).toByteArray())
System.out.format("%02x ", b & 0xff);
Prints
05 5a a5 4d 36 e2 0c 6a d2
Storing a number in binary form is theoretically the most efficient way since every combination of bits is a distinct legal value.
You may have other options only if there is more redundancy in your input, that is there are some constraints on the legal digit combinations.
The way you specify it, this is not possible. There simply are more 20 digit numbers than there are 6 digit numbers, so if you map 20 digits to only six digits, some 20 digit numbers will have to be mapped to the same six digit number. If you know that not all numbers will be valid or even have the same likelyhood, this can be used for compression, but otherwise this is impossible.
Although a reversible (bijective) mapping from 20 digit numbers to six digit numbers is impossible it is still possible to map long numbers to shorter output. This works by reducing the requirement that the output needs to be a number. The only important consideration is that the output sequence needs to have the same number of possibilities as the input. Here is an example:
There are 10^20 possible 20 digit numbers
If you use a sequence of full 8-bit ASCII (256 characters) of length x you will have 256^x possible outputs. If you solve this for x, you will notice that 256^9 > 10^20 so 9 ASCII characters are enough to encode 20^10 possible numerical inputs.
Marko's answer to the same question will tell you how to convert a number to it's byte representation which may be used as input. But be aware that this input will not be numerical and may contain many strange symbols.
i am developing a piece of code to generate a unique hexadecimal value from an input string. The output size must be less than 11 bytes which comes as requirement.Can someone please give me an insight into this. I have done the string to binary conversion and then the hexagonal mapping which produces a combination of alphanumeric characters but the size is always greater tha 11 bytes. I also need to regenerate the input from this unique id..Is that possible.....
Thanks in adavance
If your result must be absolutely unique and your input can be any length, then your task is impossible.
Think of it that way: how many different combinations of 11 bytes are there? 25611 (or 211*8=288).
That's a big number, right? Yes, but it's not big enough.
For simplicities sake we'll talk about ASCII strings only, so we have 128 different values (in reality there are many more possibilities for a character in a Java String, but the principle stays the same. For simplicities sake we also ignore that a \0 character in a String is kind of unlikely).
Now, there are 12813 different 13-character ASCII strings. That's 27*13 or 291 different combinations. Obviously you can't have a unique id out of 288 possible ids for 291 different strings.
Less than 11 bytes means maximum 10 bytes.
8^10 is 1073741824.
2^80 is a huge number.
So if you take your hexvalue, and take it modulo that number, you should fit into the 10 bytes. Convert the remainder back to hex.
Regenerating the input will not be possible. If your input is allowed to be longer than 11 bytes, it will not be possible. That would be an endless compression.
Lets say I have a number 345, I want to have so that I end up with 0345. I.e.
int i = 0345;
How can I take an existing number and shift it along or append a 0.
I know you are talking about an int, but maybe what you want is to pad a number with leading 0s. A quick way is with the String.format static method.
int num = 345;
String.format("%04d", num);
would return:
"0345"
The 4d tells it to add 0s to the left if it has less than 4 digits, so you can change it to a 5 and it would give you:
"00345"
Using a 0 on the start of the number when declaring it means it's octal, so 0345 is actually 229 in decimal. I'm not sure how you expect to add a zero to a number using bitwise operations, which work on the binary representation of the number. If you want to add it to the decimal representation, it won't mean anything, since the number is always stored in binary, and the value is converted for your convenience to decimal when being displayed. When doing any computations, the decimal value is not important, only the binary one.
If you're interested only in displaying the value with a 0 at the start, then you could append the 0 to a String containing that number which can be easily done like this "0" + i.