I'm trying to create a partition function that accepts three parameters: a text string, a pattern string, and an integer k.
The goal is to store the contents of the pattern of length m in a string array of k+1 fragments, where each fragment is of length m/k+1 (or as close to).
For instance if the string "ABCDEFGHIJKLMNOPQRSTUVWXYZ" is parsed to the method where k = 2
The array should look something like this [ABCDEFGHI, JKLMNOPQ, RSTUVWXYZ]
The program runs fine when m/k+1 is divided evenly, however when result produces a remainder the results are off. I’ve noticed that the errors seems to correspond with the remainder of m/k+1
This is the part of the code I'm having problems with:
public static String[] partition(String text, String pattern, int k) {
String[] fragment = new String[k+1];
int f = k+1;
int m = pattern.length();
int fragmentSize = (int)Math.floor(m/f);
int lastCharIndex;
// cannot partition evenly{
int i = 0;
while(i < f) {
// set the first partition as the largest
if(fragment[i] == fragment[0]) {
fragmentSize = (int)Math.ceil(m/f);
lastCharIndex = i * fragmentSize;
fragment[i] = pattern.substring(lastCharIndex, lastCharIndex+fragmentSize);
}
else {
fragmentSize = (int)Math.floor(m/f);
lastCharIndex = i * fragmentSize;
fragment[i] = pattern.substring(lastCharIndex, lastCharIndex+fragmentSize);
}
i++;
}
return fragment;
Using the example above the output I’m currently receiving is [ABCDEFGHI, IJKLMNOP, QRSTUVWX]
I have a feeling it has something to do with the explicit cast of fragmentSize, but I can't figure out a way around it.
Any help would be much appreciated.
Your logic is incorrect. Let's say you have 26 letters, and want 3 fragments. That makes a first fragment of 9 elements, a second of 9 elements, and a last one of 8 elements.
Your logic makes each fragments of length 8 (floor(26 / 3)), except the first one, which is of length 9 (ceil(26 / 3)). Not only that, but you add the additional letter of the first fragment to the second one.
Side note: the test if(fragment[i] == fragment[0]) should in fact be if (i == 0). And you should make your numbers double to avoid losing the decimal part.
All your operations are made with int, which means two things :
they also produce int, and you loose the decimal part
your calls to Math.ceiland Math.floor are useless : they need a double as argument but already get an int (as you pass the result of an operation involving only int), there is no floor or ceil to be made.
You should start use double when declaring f and m :
double f = (double) k+1;
double m = (double) pattern.length();
Related
I am trying to print a list of random even numbers (5 times) using a bounds. Example being from 0 to 30 (including both those numbers). This is what I have so far (this is in its own class):
public int nextEven(int h){
int n = rand.nextEven(h) % 2;
return n;
}
This is where it would print from my main method:
System.out.println("Random Even:");
for (int i = 0; i < 5; i++){
System.out.println(rand.nextEven(30));
}
When I run the program it gives me an error and I am not quite sure how to solve this. This is an example of the desired output of even numbers from 0 to 30:
4
26
12
10
20
It isn't clear why taking the remainder of 2 would yield an even number. Instead, generate a number in the range 0 to h / 2 and then multiply the result of that by 2. Like,
public int nextEven(int h){
int n = ThreadLocalRandom.current().nextInt(1 + (h / 2)); // 0 to (h / 2) inclusive
return n * 2; // n * 2 is even (or zero).
}
What exactly is rand? Is it the Random class or an instance of your own class?
Since you want to do something with inheritance I guess you want to overwrite a method, but if rand is an instance of the java Random class this won't work.
The error probably comes from recursively calling nextEven method forever.
If you could clarify what exactly you want to do?
I see at least two solutions.
The first one supposes that random + 1 = random. I mean, that if you add or subtract a random number you still get a valid random number. That's why you can use Random class to generate a value in the desired period and then add or subtract one it the number is odd.
The second approach is just to generate an array of even values for the desired period. Then take a random value from this array.
The mod operator % will give you the remainder of the first value divided by the second.
value % 2
... will return 0 if value is even, or 1 if value is odd.
Since rand is a reference to an instance of the class containing your code, you have an infinite recursion. What you really need is something like:
public int nextEven(int h){
int evenRandomValue;
do {
evenRandomValue = (int)(Math.random() * (h + 1));
} while(evenRandomValue % 2 == 1);
return evenRandomValue;
}
Here is a quite explicit way to achieve this using streams:
List<Integer> myRandomInts = Random.ints(lower, upper + 1)
.filter(i -> i % 2 == 0)
.limit(5).boxed()
.collect(Collectors.toList());
This can be read as 'generate an infinite stream of random numbers between given bounds, filter out odds, take the first 5, turn into Integer objects and then collect into a list.
Note: I deleted this post earlier because I found the following post but I'm not sure how to apply it to my problem.
I'm working on a transposition cipher decoder. I have already solved the problem of static columns (1,2,3,4 kept in order), but I'm not sure how to create an array of each possible permutation of a length(Given as a parameter), I understand the easiest way is some kind of recursive method, but whilst attempting this I keep getting lost in the endeavour. (I've been coding all day and am quite tired)
Example array would contain:
1,2,3,4,5,6
2,1,3,4,5,6
2,3,1,4,5,6
...
After being very confused for awhile, and trying a few different things, a friend of mine (Not a user here) gave me the following java solution:
public static void main(String[] args) {
Nibba nib = new Nibba();
List<Character> characterSet = new ArrayList<>();
characterSet.add('1');
characterSet.add('2');
characterSet.add('3');
characterSet.add('4');
characterSet.add('5');
characterSet.add('6');
List<String> perms = nib.generatePermutations(characterSet);
// filter only the permutations of length 6
perms = perms.stream().filter(p -> p.length() == characterSet
.size()).collect(Collectors.toList());
for (String s : perms) {
System.out.println(s);
}
System.out.println("Total permutations = " + perms.size());
}
private List<String> generatePermutations(List<Character> characterSet) {
List<String> permutations = new ArrayList<>();
for (int idx = 0; idx < characterSet.size(); idx++) {
char character = characterSet.get(idx);
// Initialise first "permutation"
if (idx == 0) {
permutations.add(String.valueOf(character));
continue;
}
ArrayList<String> oldPerms = new ArrayList<>(permutations);
for (String subPermutation : oldPerms) {
insertPermutations(permutations, subPermutation, character);
}
}
return permutations;
}
/**
* Insert permutations into the given list
*
* #param list the list
* #param str the string
* #param c the character to insert at each point in the string
*/
private void insertPermutations(List<String> list, String str, char c) {
for (int i = 0; i <= str.length(); i++) {
String newStr = str.substring(0, i) + c + str.substring(i);
list.add(newStr);
}
}
Recall that there are n! permutations of n items. The n! can be easily understood in the following way:
1. There are `n` options for choosing the first item.
2. There are `n-1` items remaining from which to choose the second item
...
n-1. There are `2` options left for the `n-1`-th item.
n. There is only 1 item left for the `n`-th position.
Thus there are (n) * (n-1) * (n-2) * ... (2) * (1) = n! total choices for how to order the items.
This directly reveals a method for enumerating the permutations using a mixed-radix numbering scheme. In this scheme, the most-significant digit will be base n, the next-most-significant digit will be base n-1..etc.
You use such a mixed-radix number to select a permutation in the following way:
Use the most significant digit to select an element from the array (note that the first digit ranges from [0, n-1], and there are n elements to select from, so you can use it as the index of the item to select.)
Remove the selected element from the array, record that it's the first element of the permuted array, and compact the remaining elements to the front of the array.
Use the second-most significant digit to select an element from the remaining items (note that the value of this digit ranges from [0, n-2], and there are n-1 digits remaining)
Remove the selected element recording it as the second element in the permuted array
Repeat until all items have been selected.
If we use an array to represent the mixed-radix number in little-endian digit order, then we would have the following:
int mixed_radix[n] = {0};
You increment this mixed-radix number in the following way:
//Increment the least-significant digit
mixed_radix[0]++;
//Ripple overflow toward the most-significant digit
for(i=0; i<n; i++) {
if(mixed_radix[i] > i) {
mixed_radix[i] = 0;
if(i < n-1)mixed_radix[i+1]++;
}
else {
break;
}
}
So we have a way to initialize the mixed-radix number to zero, and then increment it through every possible value, stopping once it wraps back around to zero. (or after n!-1 increments...)
All that said, there's a lovely numerical trick that can make this even simpler: You can unpack that ugly mixed-radix number from an integer in the following way:
We know that there are n! permutations of n items; for any integer val in the range [0, n!-1] the following provides a bijective mapping between the integer value and a mixed-radix number:
int working = val; //val in the range [0, n!-1]
for(j=0 j<n; j++) {
mixed_radix[j] = working % (j+1);
working /= (j+1);
}
So embedding this "unpacking" loop within an outer loop that runs val over the range 0 to n!-1 is a much denser method to enumerate the mixed-radix numbers (which enumerates the possible permutations). It also assigns an integer to each permutation, effectively naming them. :)
I have an array of operations and a target number.
The operations could be
+ 3
- 3
* 4
/ 2
I want to find out how close I can get to the target number by using those operations.
I start from 0 and I need to iterate through the operations in that order, and I can choose to either use the operation or not use it.
So if the target number is 13, I can use + 3 and * 4 to get 12 which is the closest I can get to the target number 13.
I guess I need to compute all possible combinations (I guess the number of calculations is thus 2^n where n is the number of operations).
I have tried to do this in java with
import java.util.*;
public class Instruction {
public static void main(String[] args) {
// create scanner
Scanner sc = new Scanner(System.in);
// number of instructions
int N = sc.nextInt();
// target number
int K = sc.nextInt();
//
String[] instructions = new String[N];
// N instructions follow
for (int i=0; i<N; i++) {
//
instructions[i] = sc.nextLine();
}
//
System.out.println(search(instructions, 0, N, 0, K, 0, K));
}
public static int search(String[] instructions, int index, int length, int progressSoFar, int targetNumber, int bestTarget, int bestDistance) {
//
for (int i=index; i<length; i++) {
// get operator
char operator = instructions[i].charAt(0);
// get number
int number = Integer.parseInt(instructions[i].split("\\s+")[1]);
//
if (operator == '+') {
progressSoFar += number;
} else if (operator == '*') {
progressSoFar *= number;
} else if (operator == '-') {
progressSoFar -= number;
} else if (operator == '/') {
progressSoFar /= number;
}
//
int distance = Math.abs(targetNumber - progressSoFar);
// if the absolute distance between progress so far
// and the target number is less than what we have
// previously accomplished, we update best distance
if (distance < bestDistance) {
bestTarget = progressSoFar;
bestDistance = distance;
}
//
if (true) {
return bestTarget;
} else {
return search(instructions, index + 1, length, progressSoFar, targetNumber, bestTarget, bestDistance);
}
}
}
}
It doesn't work yet, but I guess I'm a little closer to solving my problem. I just don't know how to end my recursion.
But maybe I don't use recursion, but should instead just list all combinations. I just don't know how to do this.
If I, for instance, have 3 operations and I want to compute all combinations, I get the 2^3 combinations
111
110
101
011
000
001
010
100
where 1 indicates that the operation is used and 0 indicates that it is not used.
It should be rather simple to do this and then choose which combination gave the best result (the number closest to the target number), but I don't know how to do this in java.
In pseudocode, you could try brute-force back-tracking, as in:
// ops: list of ops that have not yet been tried out
// target: goal result
// currentOps: list of ops used so far
// best: reference to the best result achieved so far (can be altered; use
// an int[1], for example)
// opsForBest: list of ops used to achieve best result so far
test(ops, target, currentOps, best, opsForBest)
if ops is now empty,
current = evaluate(currentOps)
if current is closer to target than best,
best = current
opsForBest = a copy of currentOps
otherwise,
// try including next op
with the next operator in ops,
test(opsAfterNext, target,
currentOps concatenated with next, best, opsForBest)
// try *not* including next op
test(opsAfterNext, target, currentOps, best, opsForBest)
This is guaranteed to find the best answer. However, it will repeat many operations once and again. You can save some time by avoiding repeat calculations, which can be achieved using a cache of "how does this subexpression evaluate". When you include the cache, you enter the realm of "dynamic programming" (= reusing earlier results in later computation).
Edit: adding a more OO-ish variant
Variant returning the best result, and avoiding the use of that best[] array-of-one. Requires the use of an auxiliary class Answer with fields ops and result.
// ops: list of ops that have not yet been tried out
// target: goal result
// currentOps: list of ops used so far
Answer test(ops, target, currentOps, opsForBest)
if ops is now empty,
return new Answer(currentOps, evaluate(currentOps))
otherwise,
// try including next op
with the next operator in ops,
Answer withOp = test(opsAfterNext, target,
currentOps concatenated with next, best, opsForBest)
// try *not* including next op
Answer withoutOp = test(opsAfterNext, target,
currentOps, best, opsForBest)
if withOp.result closer to target than withoutOp.target,
return withOp
else
return withoutOp
Dynamic programming
If the target value is t, and there are n operations in the list, and the largest absolute value you can create by combining some subsequence of them is k, and the absolute value of the product of all values that appear as an operand of a division operation is d, then there's a simple O(dkn)-time and -space dynamic programming algorithm that determines whether it's possible to compute the value i using some subset of the first j operations and stores this answer (a single bit) in dp[i][j]:
dp[i][j] = dp[i][j-1] || dp[invOp(i, j)][j-1]
where invOp(i, j) computes the inverse of the jth operation on the value i. Note that if the jth operation is a multiplication by, say, x, and i is not divisible by x, then the operation is considered to have no inverse, and the term dp[invOp(i, j)][j-1] is deemed to evaluate to false. All other operations have unique inverses.
To avoid loss-of-precision problems with floating point code, first multiply the original target value t, as well as all operands to addition and subtraction operations, by d. This ensures that any division operation / x we encounter will only ever be applied to a value that is known to be divisible by x. We will essentially be working throughout with integer multiples of 1/d.
Because some operations (namely subtractions and divisions) require solving subproblems for higher target values, we cannot in general calculate dp[i][j] in a bottom-up way. Instead we can use memoisation of the top-down recursion, starting at the (scaled) target value t*d and working outwards in steps of 1 in each direction.
C++ implementation
I've implemented this in C++ at https://ideone.com/hU1Rpq. The "interesting" part is canReach(i, j); the functions preceding this are just plumbing to handle the memoisation table. Specify the inputs on stdin with the target value first, then a space-separated list of operations in which operators immediately preceed their operand values, e.g.
10 +8 +11 /2
or
10 +4000 +5500 /1000
The second example, which should give the same answer (9.5) as the first, seems to be around the ideone (and my) memory limits, although this could be extended somewhat by using long long int instead of int and a 2-bit table for _m[][][] instead of wasting a full byte on each entry.
Exponential worst-case time and space complexity
Note that in general, dk or even just k by itself could be exponential in the size of the input: e.g. if there is an addition, followed by n-1 multiplication operations, each of which involves a number larger than 1. It's not too difficult to compute k exactly via a different DP that simply looks for the largest and smallest numbers reachable using the first i operations for all 1 <= i <= n, but all we really need is an upper bound, and it's easy enough to get a (somewhat loose) one: simply discard the signs of all multiplication operands, convert all - operations to + operations, and then perform all multiplication and addition operations (i.e., ignoring divisions).
There are other optimisations that could be applied, for example dividing through by any common factor.
Here's a Java 8 example, using memoization. I wonder if annealing can be applied...
public class Tester {
public static interface Operation {
public int doOperation(int cur);
}
static Operation ops[] = { // lambdas for the opertions
(x -> x + 3),
(x -> x - 3),
(x -> x * 4),
(x -> x / 2),
};
private static int getTarget(){
return 2;
}
public static void main (String args[]){
int map[];
int val = 0;
int MAX_BITMASK = (1 << ops.length) - 1;//means ops.length < 31 [int overflow]
map = new int[MAX_BITMASK];
map[0] = val;
final int target = getTarget();// To get rid of dead code warning
int closest = val, delta = target < 0? -target: target;
int bestSeq = 0;
if (0 == target) {
System.out.println("Winning sequence: Do nothing");
}
int lastBitMask = 0, opIndex = 0;
int i = 0;
for (i = 1; i < MAX_BITMASK; i++){// brute force algo
val = map[i & lastBitMask]; // get prev memoized value
val = ops[opIndex].doOperation(val); // compute
map[i] = val; //add new memo
//the rest just logic to find the closest
// except the last part
int d = val - target;
d = d < 0? -d: d;
if (d < delta) {
bestSeq = i;
closest = val;
delta = d;
}
if (val == target){ // no point to continue
break;
}
//advance memo mask 0b001 to 0b011 to 0b111, etc.
// as well as the computing operation.
if ((i & (i + 1)) == 0){ // check for 2^n -1
lastBitMask = (lastBitMask << 1) + 1;
opIndex++;
}
}
System.out.println("Winning sequence: " + bestSeq);
System.out.println("Closest to \'" + target + "\' is: " + closest);
}
}
Worth noting, the "winning sequence" is the bit representation (displayed as decimal) of what was used and what wasn't, as the OP has done in the question.
For Those of you coming from Java 7, this is what I was referencing for lambdas: Lambda Expressionsin GUI Applications. So if you're constrained to 7, you can still make this work quite easily.
I wrote an app that converts from decimal to binary, octal, hex and vice versa. I initially wrote it using integers (int) however and while it worked perfectly, it stopped working after the number was a certain size. So I looked around and saw in order to get passed this I'd have to use long. I got my decimal to binary to work well but my method for converting binary back to decimal is still not working passed a certain length. Any help would be much appreciated
public static long getDecimal(long input) {
// Converts the input integer to a String, so we can use charAt and multiply the 1's and 0's by their corresponding power
String inputString = Long.toString(input);
// Decimal is our final decimal output, i our itterator, mult our power and num is a temporary place holder
long decimal = 0;
int i = (inputString.length() - 1);
long mult = 1;
long num = 0;
// As long as our itterator isn't below 0
while (i >= 0) {
// Num, the placeholder, is the value of the character at the index of our itterator, multuplied by our power
num = (Character.getNumericValue(inputString.charAt(i)) * mult);
// Add this our final number
decimal = decimal + num;
// Multiply our power by 2 to get the next one
mult = mult * 2;
// Decrease our itterator by 1
i--;
}
return decimal;
}
I suggest changing the getDecimal(long input) method to take a String instead of a long, for two reasons:
The method expects the parameter to look like a binary value, such as 10010011. That is very unexpected for a method taking a long.
The largest value this method can handle is 1111111111111111111L
It would be much better this way:
getDecimal(String binaryNum)
Notice that the parameter name hints to the read what kind of value it expects.
With this change, the method will be able to handle much larger inputs, up to 11111111111111111111111111111111111111111111111111111111111111, also known as Long.MAX_VALUE.
Other than this, the method seems to be working correctly.
Suppose I have a method to calculate combinations of r items from n items:
public static long combi(int n, int r) {
if ( r == n) return 1;
long numr = 1;
for(int i=n; i > (n-r); i--) {
numr *=i;
}
return numr/fact(r);
}
public static long fact(int n) {
long rs = 1;
if(n <2) return 1;
for (int i=2; i<=n; i++) {
rs *=i;
}
return rs;
}
As you can see it involves factorial which can easily overflow the result. For example if I have fact(200) for the foctorial method I get zero. The question is why do I get zero?
Secondly how do I deal with overflow in above context? The method should return largest possible number to fit in long if the result is too big instead of returning wrong answer.
One approach (but this could be wrong) is that if the result exceed some large number for example 1,400,000,000 then return remainder of result modulo
1,400,000,001. Can you explain what this means and how can I do that in Java?
Note that I do not guarantee that above methods are accurate for calculating factorial and combinations. Extra bonus if you can find errors and correct them.
Note that I can only use int or long and if it is unavoidable, can also use double. Other data types are not allowed.
I am not sure who marked this question as homework. This is NOT homework. I wish it was homework and i was back to future, young student at university. But I am old with more than 10 years working as programmer. I just want to practice developing highly optimized solutions in Java. In our times at university, Internet did not even exist. Today's students are lucky that they can even post their homework on site like SO.
Use the multiplicative formula, instead of the factorial formula.
Since its homework, I won't want to just give you a solution. However a hint I will give is that instead of calculating two large numbers and dividing the result, try calculating both together. e.g. calculate the numerator until its about to over flow, then calculate the denominator. In this last step you can chose the divide the numerator instead of multiplying the denominator. This stops both values from getting really large when the ratio of the two is relatively small.
I got this result before an overflow was detected.
combi(61,30) = 232714176627630544 which is 2.52% of Long.MAX_VALUE
The only "bug" I found in your code is not having any overflow detection, since you know its likely to be a problem. ;)
To answer your first question (why did you get zero), the values of fact() as computed by modular arithmetic were such that you hit a result with all 64 bits zero! Change your fact code to this:
public static long fact(int n) {
long rs = 1;
if( n <2) return 1;
for (int i=2; i<=n; i++) {
rs *=i;
System.out.println(rs);
}
return rs;
}
Take a look at the outputs! They are very interesting.
Now onto the second question....
It looks like you want to give exact integer (er, long) answers for values of n and r that fit, and throw an exception if they do not. This is a fair exercise.
To do this properly you should not use factorial at all. The trick is to recognize that C(n,r) can be computed incrementally by adding terms. This can be done using recursion with memoization, or by the multiplicative formula mentioned by Stefan Kendall.
As you accumulate the results into a long variable that you will use for your answer, check the value after each addition to see if it goes negative. When it does, throw an exception. If it stays positive, you can safely return your accumulated result as your answer.
To see why this works consider Pascal's triangle
1
1 1
1 2 1
1 3 3 1
1 4 6 4 1
1 5 10 10 5 1
1 6 15 20 15 6 1
which is generated like so:
C(0,0) = 1 (base case)
C(1,0) = 1 (base case)
C(1,1) = 1 (base case)
C(2,0) = 1 (base case)
C(2,1) = C(1,0) + C(1,1) = 2
C(2,2) = 1 (base case)
C(3,0) = 1 (base case)
C(3,1) = C(2,0) + C(2,1) = 3
C(3,2) = C(2,1) + C(2,2) = 3
...
When computing the value of C(n,r) using memoization, store the results of recursive invocations as you encounter them in a suitable structure such as an array or hashmap. Each value is the sum of two smaller numbers. The numbers start small and are always positive. Whenever you compute a new value (let's call it a subterm) you are adding smaller positive numbers. Recall from your computer organization class that whenever you add two modular positive numbers, there is an overflow if and only if the sum is negative. It only takes one overflow in the whole process for you to know that the C(n,r) you are looking for is too large.
This line of argument could be turned into a nice inductive proof, but that might be for another assignment, and perhaps another StackExchange site.
ADDENDUM
Here is a complete application you can run. (I haven't figured out how to get Java to run on codepad and ideone).
/**
* A demo showing how to do combinations using recursion and memoization, while detecting
* results that cannot fit in 64 bits.
*/
public class CombinationExample {
/**
* Returns the number of combinatios of r things out of n total.
*/
public static long combi(int n, int r) {
long[][] cache = new long[n + 1][n + 1];
if (n < 0 || r > n) {
throw new IllegalArgumentException("Nonsense args");
}
return c(n, r, cache);
}
/**
* Recursive helper for combi.
*/
private static long c(int n, int r, long[][] cache) {
if (r == 0 || r == n) {
return cache[n][r] = 1;
} else if (cache[n][r] != 0) {
return cache[n][r];
} else {
cache[n][r] = c(n-1, r-1, cache) + c(n-1, r, cache);
if (cache[n][r] < 0) {
throw new RuntimeException("Woops too big");
}
return cache[n][r];
}
}
/**
* Prints out a few example invocations.
*/
public static void main(String[] args) {
String[] data = ("0,0,3,1,4,4,5,2,10,0,10,10,10,4,9,7,70,8,295,100," +
"34,88,-2,7,9,-1,90,0,90,1,90,2,90,3,90,8,90,24").split(",");
for (int i = 0; i < data.length; i += 2) {
int n = Integer.valueOf(data[i]);
int r = Integer.valueOf(data[i + 1]);
System.out.printf("C(%d,%d) = ", n, r);
try {
System.out.println(combi(n, r));
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
}
}
Hope it is useful. It's just a quick hack so you might want to clean it up a little.... Also note that a good solution would use proper unit testing, although this code does give nice output.
You can use the java.math.BigInteger class to deal with arbitrarily large numbers.
If you make the return type double, it can handle up to fact(170), but you'll lose some precision because of the nature of double (I don't know why you'd need exact precision for such huge numbers).
For input over 170, the result is infinity
Note that java.lang.Long includes constants for the min and max values for a long.
When you add together two signed 2s-complement positive values of a given size, and the result overflows, the result will be negative. Bit-wise, it will be the same bits you would have gotten with a larger representation, only the high-order bit will be truncated away.
Multiplying is a bit more complicated, unfortunately, since you can overflow by more than one bit.
But you can multiply in parts. Basically you break the to multipliers into low and high halves (or more than that, if you already have an "overflowed" value), perform the four possible multiplications between the four halves, then recombine the results. (It's really just like doing decimal multiplication by hand, but each "digit" is, say, 32 bits.)
You can copy the code from java.math.BigInteger to deal with arbitrarily large numbers. Go ahead and plagiarize.