In my computer science class, I was given an algorithm to multiply two same-length binary numbers. I was instructed to convert it to multiply base 256 numbers and implement it in Java, but I can't seem to get the correct output and I don't know what I'm missing.
The algorithm that I was given:
MULTIPLY(U,V)
define array W[1..2n] for k = 1 to 2n
W[k] = 0 // Initialize result
for j=1 to n
c = 0 // Carry bit
for i = 1 to n
t = U[i]V[ j] + W [i+j] + c
W[i+j] = t mod 2 // lower bit
c= 𝑡/2 // upper bit
k = i+j
while k ≤ 2n and c ≠ 0 // propagate carry bit
t=W[k]+ c
W[k]=tmod2 // lower bit
c=𝑡/2 // upper bit
k++
return W
My attempt:
private static Byte[] bruteMultiply(Byte[] U, Byte[] V) {
Byte[] W = new Byte[U.length * 2];
for (int k = 0; k < W.length; k++) {
W[k] = 0;
}
for (int j = 0; j < U.length; j++) {
int c = 0;
for (int i = 0; i < U.length; i++) {
int t = (U[i] & 0xFF) * (V[j] & 0xFF) + (W[i + j] & 0xFF) + c;
W[i + j] = (byte) (t % 256);
c = t / 256;
}
int k = U.length + j;
while ((k < 2 * U.length) && (c != 0)) {
int t = (W[k] & 0xFF) + c;
W[k] = (byte) (t % 256);
c = t / 256;
k++;
}
}
return W;
}
When I feed it the arrays [197, 33, 151, 79] and [248, 164, 50, 235], I get [216, 234, 132, 91, 206, 122, 31, 73] when [191, 118, 251, 78, 251, 255, 83, 133] was expected.
I don't know what I'm missing or where I went wrong. Any suggestions or pointers would be helpful!
Hint: try to multiply [79, 151,33, 197] and [235, 50, 164, 248] with your code instead and compare the result to the target result.
I believe it is time for you to learn about the endianness. Generally your implementation looks OK but you use different endianness from the one in the example. Once you fix it, I think you'll get the correct answer.
P.S. I see no good reason to use Byte rather than byte in your array. This is another tricky difference that you probably should learn about.
Related
An array of size s + 1 is initialized such that a[i] = i for 0 <= i < s , a[s] = 0. Then I iteratively use dynamic programming to sum the values of the array, going from largest to smallest, doing it t times. Results get large very quickly so I reduce them mod some modulus.
If s = 10, the arrays look like this:
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0]
[0, 45, 44, 42, 39, 35, 30, 24, 17, 9, 0]
[0, 45, 89, 131, 170, 205, 235, 259, 276, 285, 0]
And so on.
After t iterations I am interested in the extreme non-zero values of the array. My algorithm does this explicitly, resulting in time complexity of O(s*t). Is there any algorithm that can produce either (or both) of these values in a better time complexity? Specifically I was thinking about whether matrix exponentiation is possible, reducing time complexity to O(s*log(t)), but really any approach is welcome as well as optimizations.
My code:
public class ArraySummation{
public static void main(String []args)
{
int s = 10;
long t = 10;
long modulus = 1000000;
long [] a = new long [s + 1];
for (int i = 1 ; i < s ; i++)
a[i] = i;
for (int i = 2 ; i <= t ; i++)
{
if ((i & 1) == 1)
for (int j = 1 ; j < a.length - 1 ; j++)
{
a[j] += a[j - 1];
if (a[j] >= modulus)
a[j] -= modulus;
}
else
for (int j = a.length - 2 ; j >= 1 ; j--)
{
a[j] += a[j + 1];
if (a[j] >= modulus)
a[j] -= modulus;
}
}
System.out.println(a[1]);
System.out.println(a[s - 1]);
}
}
For s=10 it can be found in OEIS https://oeis.org/A030113 as a linear recurrence.
There is also a formula in matrix form for all s
(PARI) k=9; M(k)=matrix(k, k, i, j, if(1-sign(i+j-k), 0, 1)); v(k)=vector(k, i, 1); a(n)=vecmax(v(k)*M(k)^n)
Sample for the matrix construction
Matrix construction
Explanation
The Matrix M operates by multiplication to Matrix T as follows to the result matrix R (short: M . T = R)
First column of R is the last column of T
Second column of R is the sum of the last and second last column of T
...
Last column of R is the sum of all columns of T
Thus the adding procedure of the question is done by matrix multiplication, but with initialization a[i] = 1. After first round with M^2 the last column contains the initialization of the question a[i] = i
M^2
Depending on the parameters s, t it could be better to use the matrix exponentiation like M^8 = M^4 . M^4 = M_4 . M_4 , M^4 = M^2 . M^2 = M_2 . M_2, where M_2 and M_4 can be reused. So instead of 8 matrix mulitiplications with only 3 multiplication we can get the result.
The complexity is O(s^2 * log(t))
I want to create an app that can open binary file, read and edit it's content in decimal values, and then save it back to binary file.
This file that I want to open have multiple parameters written in 2 bytes. e.g. 00 06 00 50 01 AB = 6, 80, 427
So far I managed to open bin file, put all data from file into byte[].
Here is the code to open and read file:
String path = getFilesDir().getAbsolutePath();
File file = new File(path + "/file.bin");
int size = (int) file.length();
byte[] bytes = new byte[size];
FileInputStream fis = new FileInputStream(file);
try {
fis.read(bytes);
...
} finally {
fis.close();
}
Here is first attempt to convert byte[] into deciaml values:
for (int i = 0; i < size / 2; i = i + 2) {
intArray[i] = ((bytes[i] & 0xff) << 8) | (bytes[i + 1] & 0xff);
}
But in this code only every second value is correct. It's shows 6,0,80,0,1 and should be 6,80,1.
The second idea was to convert byte[] into String[] and then into e.g. int[] but It doesn't work as intended. In this fragment I didn't parse whole array, but only hexArray[4] which was 50 in hex and 80 in dec, but the result was 50.
for (int i = 0; i < size; i = i + 2) {
num1 = String.format("%02X", bytes[i] & 0xFF);
num2 = String.format("%02X", bytes[i + 1] & 0xFF);
String twoByte = num1 + num2;
hexArrayWithNull[i] = twoByte;
}
String[] hexArray = Arrays.stream(hexArrayWithNull).filter(Objects::nonNull).toArray(String[]::new);
num = String.format("%d", Integer.parseInt(hexArray[4]));
I'm quite stuck here and need some guidance. I must say also that I'm new in programming.
Thanks
You increment i in each iteration by 2 and you store in intArray[i]. So, you store in index [0] then index [2] then index [4] and so on. This explains the zeros at odd indices [1], [3], ...
Also, you must continue the loop until size, not size/2.
Here is the correct loop:
for (int i = 0; i < size; i = i + 2) {
intArray[i/2] = ((bytes[i] & 0xff) << 8) | (bytes[i + 1] & 0xff);
}
Here is the another possibility:
for (int i = 0; i < size/2; i = i + 1) {
intArray[i] = ((bytes[2*i] & 0xff) << 8) | (bytes[2*i + 1] & 0xff);
}
[EDIT]
The reverse operation would be:
for (int i = 0; i < size/2; i = i + 1) {
bytes[2*i] = (intArray[i] & 0xff00) / 256; //or >>8 instead of /256
bytes[2*i+1] = intArray[i] & 0xff;
}
I'm new to objective-c and I don't understand Java very well, my question:
I have this code in Java that verifies the Bank identification number:
public static boolean isValidNIB(String nib) {
char[] toValidate = nib.substring(0, 19).toCharArray();
Integer checkDigit = Integer.valueOf(nib.substring(19));
Integer[] wi = { 73, 17, 89, 38, 62, 45, 53, 15, 50, 5, 49, 34, 81, 76, 27, 90, 9, 30, 3 };
Integer sum = 0;
for (int i = 0; i < 19; i++) {
sum += Character.digit(toValidate[i], 10) * wi[i];
}
return checkDigit.equals(98 - (sum % 97));
}
I need to convert this code into objective-c, the problem is that I can't make It work...
Here is my attempt to translate the java code into objective-c:
NSString *nib = #"003500970000199613031"; //UNICEF NIB :P
//transforms nsstring to array of chars
NSMutableArray *chars = [[NSMutableArray alloc] initWithCapacity:[nib length]];
for (int i=0; i < [nib length]; i++) {
NSString *ichar = [NSString stringWithFormat:#"%C", [nib characterAtIndex:i]];
[chars addObject:ichar];
}
NSLog(#"array nib = %#",chars);
//retrieves the first 19 chars
NSMutableArray *toValidate = [[NSMutableArray alloc] init];
for (int i=0; i < chars.count; i++) {
if (i <= 19) {
[toValidate addObject:[chars objectAtIndex:i]];
}
}
NSLog(#"array toValidate = %#",toValidate);
NSString * checkDigit = [nib substringWithRange:NSMakeRange(19, 1)];
NSArray *weight = [NSArray arrayWithObjects:#"73", #"17", #"89", #"38", #"62", #"45", #"53", #"15", #"50", #"5", #"49", #"34", #"81", #"76", #"27", #"90", #"9", #"30", #"3", nil];
NSInteger sum = 0;
for (int i = 0; i < weight.count ; i++) {
sum += [[toValidate objectAtIndex:i] integerValue] * [[weight objectAtIndex:i] integerValue];
}
if (checkDigit.integerValue == (98 -(sum % 97))) {
NSLog(#"VALD");
}else{
NSLog(#"NOT VALID");
}
I'm sure that this is not the correct approach but It's something.
Thanks in Advance.
There is at least one error. Your
NSString * checkDigit = [nib substringWithRange:NSMakeRange(19, 1)];
returns only one character (at position 19) from the identification number (in this case
"3"), but
Integer checkDigit = Integer.valueOf(nib.substring(19));
computes the value of the substring starting at position 19 (in this case: "31").
Therefore the calculated checksum does not match the expected value.
But there is also a lot of unnecessary computations in your code, and there is
no reason to store the weights in an array of strings.
The method can be shortened to:
NSString *nib = #"003500970000199613031";
int weight[] = { 73, 17, 89, 38, 62, 45, 53, 15, 50, 5, 49, 34, 81, 76, 27, 90, 9, 30, 3 };
NSInteger sum = 0;
for (int i = 0; i < 19; i++) {
sum += [[nib substringWithRange:NSMakeRange(i, 1)] intValue] * weight[i];
}
int checkDigit = [[nib substringFromIndex:19] intValue];
if (checkDigit == (98 - (sum % 97))) {
NSLog(#"VALID");
} else {
NSLog(#"NOT VALID");
}
And the output is "VALID".
I want to know the size of byte of my interger. Example :
public static void main(String[] args) throws IOException {
int a = 256;
System.out.println(nbBytes(a));
}
static byte nbBytes(int value) {
byte l = 0;
while (value != 0) {
value >>>= 8;
++l;
}
return l;
}
It works perfectly, But i want to optimize this calculation.
Have you a proposition ? :D
If you mean runtime performance, the following algorithm (which originally finds the highest set bit) is probably fastest. I've already modified it to return the number of bytes required to encode the integer argument:
private static final int[] DE_BRUIJN_BIT_POSITION_LUT = {
0, 9, 1, 10, 13, 21, 2, 29, 11, 14, 16, 18, 22, 25, 3, 30,
8, 12, 20, 28, 15, 17, 24, 7, 19, 27, 23, 6, 26, 5, 4, 31
};
public static int nbBytes2(int n) {
n |= n >> 1;
n |= n >> 2;
n |= n >> 4;
n |= n >> 8;
n |= n >> 16;
return DE_BRUIJN_BIT_POSITION_LUT[((n * 0x07C4ACDD) >> 27) & 0x1f] / 8 + 1;
}
Even if it looks more complicated, it does not have any loops or conditional processing, which allows optimal use of modern CPU pipelines.
Comparing the De Bruijn algorithm to your method, your method is ~4 times faster for inputs in the range 0x0-0xff (your method won't branch either). For inputs in the range 0x100-0xfff, my method is 19 times faster, for inputs 0x10000-0xffffff 28 times faster and for inputs >0x1000000 35 times faster. All numbers are valid for my hardware, on other computers it may of course differ.
In Java, an int is always a 32-bit, signed 2's-complement value. See, for instance, Section 2.3 of the Java Virtual Machine Specification.
If you want to know the minimum number of bits to store a particular value, you can use Integer.numberOfLeadingZeros to get that:
int bitsNeeded = 32 - Integer.numberOfLeadingZeros(value);
You can then round up to get the number of bytes needed.
If you're running an older version of Java that doesn't include this function, here's the 1.6 source for it:
public static int numberOfLeadingZeros(int i) {
if (i == 0)
return 32;
int n = 1;
if (i >>> 16 == 0) { n += 16; i <<= 16; }
if (i >>> 24 == 0) { n += 8; i <<= 8; }
if (i >>> 28 == 0) { n += 4; i <<= 4; }
if (i >>> 30 == 0) { n += 2; i <<= 2; }
n -= i >>> 31;
return n;
}
Whether this is more efficient than what you are already doing can only be determined, I think, by profiling. It will depend, as well, on the distribution of values that you expect to encounter.
If you only expect to deal with non-negative values, I would do this:
static byte nBytes(int value) {
if (value < (1 << 8)) return 1;
if (value < (1 << 16)) return 2;
if (value < (1 << 24)) return 3;
return 4;
}
This assumes that you require 1 byte to represent zero. To handle negative numbers, there are two logical choices:
Always return 4
Return the minimum number of bytes necessary to represent the value in 2's complement.
For the second case, I would do the following:
static byte nBytes(int value) {
if (value < 0) {
if (value > Integer.MIN_VALUE) {
value = -value;
if (value < (1 << 7)) return 1;
if (value < (1 << 15)) return 2;
if (value < (1 << 23)) return 3;
}
} else {
if (value < (1 << 8)) return 1;
if (value < (1 << 16)) return 2;
if (value < (1 << 24)) return 3;
}
return 4;
}
I don't know it this is more optimum, but another solution is something like (not tested):
return (byte)Math.ceil(Integer.toBinaryString(value).length()/8.0);
Given the byte array:
{255, 3, 5}
which is equivalent to:
{11111111, 00000011, 00000101}
I'd like to get the following result:
{23,22,21,20,19,18,17,16, 9,8, 2,0}
Which is an array of the indices of 1's in the input array.
What's the fastest way of doing this in Java?
Update:
I've chosen the fastest solution, which #aioobe's. Here are the test results of a pretty big data test:
#aioobe's way:
35s 289ms
35s 991ms
36s 174ms
#Martijn's way:
39s 274ms
39s 879ms
38s 684ms
Thanks you all! I appreciate your help.
What's the fastest way of doing this in Java?
Presumably by a 256 entry look-up table of the type int[][] in which lut[yourByte] equals the array of indexes for the ones in yourByte.
You then just do something like
for (int i = 0; i < bytes.length; i++)
for (int indexes : lut[bytes[i]])
appendToResult(indexes + (bytes.length - 1 - i) * 8);
Tested code (http://ideone.com/7NUjY):
public static List<Integer> getBitsIndices(byte[] input, boolean b)
{
List<Integer> list = new ArrayList<Integer>();
for (int i = 0; i < input.length; ++i)
{
byte j = input[i];
for (int k = 7, bit = 1 << 7; k >= 0; --k, bit >>>= 1)
{
if ((j & bit) == bit == b)
{
list.add((input.length - i) * 8 - (8 - k));
}
}
}
return list;
}
Use it this way:
byte[] input = {(byte) 255, (byte) 3, (byte) 5};
System.out.println(getBitsIndices(input, true));
Output:
[23, 22, 21, 20, 19, 18, 17, 16, 9, 8, 2, 0]
I would (given {255, 3, 5} in integer) and always the last bit with 0x1 and then shift to the right.
Both operations are fast and have native CPU support.
Example:
pos, index = 0; res[];
00000101 AND 0x1 -> TRUE; res[index++] = pos++;
shift right
00000010 AND 0x1 -> FALSE; pos++;
shift right
... and so on.
I will make a test implementation this evening.