Issue with Java simple arithmetic - java

I'm working on a small Java program, and somewhere, my calculations are going awry. My code is as follows:
import java.io.*;
import java.util.*;
import java.text.*;
public class NumManip
{
public static void main(String args[])
{
Scanner numGetter = new Scanner(System.in);
final int MULT_1 = 9;
final int MULT_2 = 12345679;
final int MULT_3 = 1000;
int poorHatedNumber;
System.out.print("Enter a digit between 1 and 9 that you dislike: ");
poorHatedNumber = numGetter.nextInt();
int num1 = poorHatedNumber * MULT_1, num2 = num1 * MULT_2;
long num3 = num2 * MULT_3;
System.out.println();
System.out.println(" " + poorHatedNumber);
System.out.println(" " + "x" + MULT_1);
System.out.println(" __");
System.out.println(" " + num1);
System.out.println(" x" + MULT_2);
System.out.println(" __");
System.out.println(" " + num2);
System.out.println(" x" + MULT_3);
System.out.println("____________");
System.out.println(num3);
}
}
I've tryed printing num1, num2, and num3 on the screen to see what the problem is, and num1 is right, num2 is right, and num3 is freaky. My input is 9, and the first calculation multiplies by 9 and gets 81. Then it multiplies that by 12345679 and gets 999999999, and then it multiplies by 1000 and gets -727380968. What's wrong with that last step? I'm REALLY new to Java, and I don't get the issue.

999999999 * 12345679 = 1.234567898765432e+16 which is way bigger than the maximum value of an int which is 2,147,483,647
Since Java uses 2-compliment method to store int number (meaning that the leftmost bit is turned on when the number is negative) this calculation "overflows" (carry-over) to the that bit which results in a negative result.
For calculation with such big numbers you should use BigDecimal

As num2 and num1 both are integer, so integer multiplication happened and it exceeds the max of integer value.
long num3 = (long)num2 * MULT_3;

I think you're resulting in a number bigger than the datatype can handle, and as the datatype is signed, it wraps around into the negatives.

Don't worry, it's not such a silly mistake really. The whole "numbers are usually a fixed size"-deal confuses just about everyone initially. Now that you know what's up, here's something even weirder. It's not really an answer to your question, but now that you've just seen an example of "bad overflow", you might find this interesting.
Consider an odd number x. There is a number y such that x * y == 1. That number y is called the modular multiplicative inverse, and it can easily be computed (see Hacker's Delight, exact division by a constant). This may seem really counter intuitive, because it essentially allows a weird kind "division" that only works if the number was an exact multiple of the divisor, and in general it allows you to "undo" a multiplication by an odd number. For example, if you have a = 3 * b, then b = -1431655765 * a - regardless of any overflow in either multiplication, so overflow need not be "destructive".

Related

subtraction operation with 2 random numbers

I am trying to create a simple math game for my son. I have the addition operation working perfect. My problem is with subtraction. I am using the same code as my addition operation, problem is sometimes the 2nd number is larger than the 1st number resulting in a negative number. I need help correcting the order of the random numbers so the 1st number is greater than or equal to the 2nd number. Please help.
Scanner input = new Scanner(System.in);
int answer;
public static void main(String[] args) {
// TODO code application logic here
int SIDES = 6;
int a = 1 + (int) (Math.random() * SIDES);
int b = 1 + (int) (Math.random() * SIDES);
System.out.println("What is " + a + " - " + b + " = ");
int difference = a - b;
Scanner one = new Scanner (System.in);
System.out.println("What is the answer?");
int answer = Integer.parseInt(one.next());
//int answer = one.next();
System.out.println("your answer is " + answer);
if (answer==difference) {
System.out.println("You are correct!");
System.out.println("You gain 5 points");
}
else{
System.out.println("You are wrong.");
System.out.println("The correct answer is " + difference);
System.out.println("You lose 5 points");
}
Just use an inequality operator to compare their values, than subtract from the larger one:
int difference = a > b ? a - b : b - a;
// ^ Inequality operator
If the ? operator is confusing you, you can alternatively write it like this:
int difference;
if(a > b) difference = a - b;
else difference = b - a;
You can read more about operators such as ?, >, &&, ||, etc. on the Equality, Relational, and Conditional Operators page.
There are many ways, but in order not to mess up your code, an easy fix would be checking the 2 generated random numbers before assigning them to a and b:
int r1 = (int) Math.random()*SIDES;
int r2 = (int) Math.random()*SIDES;
int a = Math.max(r1, r2);
int b = Math.min(r1, r2);
This way, a will always be greater or equals to b.
You can make sure that your b never becomes bigger than a by adjusting your random number generation logic:
int b = 1 + (int) (Math.random() * a);
That's probably better than swapping the numbers, because swapping will skew a to the high end (close to SIDES) which may not be what you want.
Since you are only subtracting two numbers you can simply use if(a >= b) then a - b else b - a to control the order.
If there are more numbers in the question you can always put all the random numbers into an array and sort them before generating the question.

Problems Generating A Math.random Number, Either 0 or 1

I want a random number, either 0 or 1 and then that will be returned to main() as in my code below.
import java.util.Scanner;
public class Exercise8Lab7 {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
int numFlips = 0;
int heads = 0;
int tails = 0;
String answer;
System.out.print("Please Enter The Number Of Coin Tosses You Want: ");
numFlips = input.nextInt();
for(int x = 1;x <= numFlips; x++){
if(coinToss() == 1){
answer = "Tails";
tails++;
}
else{
answer = "Heads";
heads++;
}
System.out.print("\nCoin Toss " + x + ": " + answer);
}
System.out.println("\n\n====== Overall Results ======" +
"\nPercentage Of Heads: " + (heads/numFlips)*100 + "\nPercentage Of Tails: " + (tails/numFlips)*100);
}
public static int coinToss(){
double rAsFloat = 1 * (2 + Math.random( ) );
int r = (int)rAsFloat;
return r;
}
}
Many solutions had been suggested to use the util.Random option which I have done and works perfectly but I want to sort out why I can't get this to work. Obviously I want the number to be an int myself so I convert it to an int after the random number has been generated. But no matter what I add or multiply the Math.random() by, it will always all either be Heads or all either be Tails. Never mixed.
Try this) It will generate number 0 or 1
Math.round( Math.random() ) ;
You could use boolean values of 0 or 1 based on value of Math.random() as a double between 0.0 and 1.0 and make the random generator much simpler. And you can get rid completely of the coinToss() method.
if(Math.random() < 0.5) {
answer = "Tails";
tails++;
}
Remove the coin toss method and replace the first conditional with the code above.
Math.random(); by itself will return a value between 0.0 and less than 1.0. If the value is in the lower half, [0.0, 0.5), then it has the same probability of being in the upper half, [0.5, 1.0). Therefore you can set any value in the lower half as true and upper as false.
Wierd that no one is using a modulo division for the random number.
This is the simplest implementation you can get:
Random rand = new Random();
int randomValue = rand.nextInt() % 2;
Math.round(Math.random()) will return either 0.0 and 1.0. Since both these values are well within the limits of int range they can be casted to int.
public static int coinToss(){
return (int)Math.round(Math.random());
}
(int)(Math.random()*2) also works fine in this case
its not working because of the integer math you are using, the call to 2+ Math.Random is pretty much always giving you a answer between 0.0 and 1.0.
so assuming that you recieve 0.25 as your result your maths is as follows
double d = 1* (2 + 0.25); // (result = 2
Then you are checking to see if your result == 1 ( which it never will. )
A better result would be to declare java.util.Random as a class variable and call random.nextBoolean() and simply perform your heads/tails calculation on that.
If you were to continue to use Math.random() and lets say
return Math.random() < 0.5
Your results would be ever so slightly skewed due to the fact that Math.random() cannot return 1.0, due to the fact that the java API specification states:
"Returns a double value with a positive sign, greater than or equal to 0.0 and less than 1.0."
Math.random() returns a random float in the range [0.0,1.0)--that means the result can be anything from 0 up to but not including 1.0.
Your code
double rAsFloat = 1 * (2 + Math.random( ) );
will take this number in the [0.0,1.0) range; adding 2 to it gives you a number in the [2.0,3.0) range; multiplying it by 1 does nothing useful; then, when you truncate it to an integer, the result is always 2.
To get integers from this kind of random function, you need to figure out how many different integers you could return, then multiply your random number by that. If you want a "0 or 1" answer, your range is 2 different integers, so multiply Math.random() by 2:
double rAsFloat = 2 * Math.random();
This gives you a random number in the range [0.0,2.0), which can then be 0 or 1 when you truncate to an integer with (int). If, instead, you wanted something that returns 1 or 2, for example, you'd just add 1 to it:
double rAsFloat = 1 + 2 * Math.random();
I think you've already figured out that the Random class gives you what you want a lot more easily. I've decided to explain all this anyway, because someday you might work on a legacy system in some old language where you really do need to work with a [0.0,1.0) random value. (OK, maybe that's not too likely any more, but who knows.)
The problem can be translated to boolean generation as follow :
public static byte get0Or1 {
Random random = new Random();
boolean res= random.nextBoolean();
if(res)return 1;
else return 0;
}
Here it the easiest way I found without using java.util.Random.
Blockquote
Scanner input = new Scanner (System.in);
System.out.println("Please enter 0 for heads or 1 for tails");
int integer = input.nextInt();
input.close();
int random = (int) (Math.random() + 0.5);
if (random == integer) {
System.out.println("correct");
}
else {
System.out.println("incorrect");
}
System.out.println(random);
This will take a random double from (0 to .99) and add .5 to make it (.5 to 1.49). It will also cast it to an int, which will make it (0 to 1). The last line is for testing.
for(int i=0;i<100;i++){
System.out.println(((int)(i*Math.random())%2));
}
use mod it will help you!
One more variant
rand.nextInt(2);
As it described in docs it will return random int value between 0 (inclusive) and the specified value (exclusive)

Randomly generating numbers until they divide exactly

I ran into a little problem here. Basically my program below is just generating two random numbers and divide both of them.
Before that I insert a statement whereby if num1 is not divisible by num2, then num2 has to generate a number between 1 to "num1" until it is divisible.
But in the end it keeps giving me a number which is not divisible (or basically giving decimal points). I tried looking for an example in the Internet and understood so well with the modulus operator. Where did I go wrong here? I just want both numbers to be divisible that's all.
Below is my code:
int num1, num2, real_ans;
Random randomGenerator = new Random();
num1 = randomGenerator.nextInt(100) + 1;
num2 = randomGenerator.nextInt(100) + 1;
if (num1%num2!=0) {
do {
num2 = randomGenerator.nextInt(num1) + 1
} while(num1%num2==0);
}
real_ans = num1 / num2;
Change the do/while loop to:
do{
num2 = randomGenerator.nextInt(num1) + 1
} while(num1 % num2 != 0);
(note the !=).
This loops until the numbers divide exactly.
you are iterating with the condition that if num1 is divisible by num2, keep iterating. Change the condition to do{...}while (num1%num2 != 0);.
You should be able to find a number that can divide num1 with that code. The only case it still won't work is when num1 is prime, so I suggest you check if num1 is prime and only generate num2, when num1 is not prime.

print the decimal equivalent of a binary number in java

My code is to print the decimal equivalent of a binary number entered by user.
import java.util.Scanner;
public class Test {
public static void main(String[] args) {
Scanner in=new Scanner(System.in);
System.out.print("Enter a binary integer: ");
int b=in.nextInt();
int digits=1;
int q=b;
//determine the number of digits
while(q/10>=1){
++digits;
q/=10;
}
System.out.println(digits);
int decimal=0;
int i=0;
//pick off the binary number's digits and calculate the decimal equivalent
while(i<=digits-1){
decimal+=b/Math.pow(10,i)%10*Math.pow(2,i);
i++;
}
System.out.println(decimal);
}
}
When I enter 1101, it outputs 13, which is the right answer. However, when I
test the number 11001, the decimal equivalent is supposed to be 25, but it outputs 26. I try
to fix it but can't find where the bug is. Can you guys help me out?
The problem is that Math.pow returns a floating-point number, and you're doing floating-point calculations where you think you're doing integer calculations. When i is 4, and you calculate
b/Math.pow(10,i)%10*Math.pow(2,i);
the calculation goes like this:
b = 11001
b / Math.pow(10,i) = b / 10000 = 1.1001 (not 1)
1.1001 % 10 = 1.1001
1.1001 * Math.pow(2,i) = 1.1001 * 16 = 17.6016 (not 16)
This is then cast to an (int) when you add it to decimal. It truncates the last value to 17, but it's too late.
Casting the Math.pow results to an (int) will make it work. But this isn't the right approach anyway. If you want to learn how to do it yourself instead of using parseInt, it's best to input the number as a String (see my earlier comment), and then you don't have to worry about picking off the bits as decimal digits or powers of 10 at all anyway. Even using your approach, instead of Math.pow it would be simpler to keep powerOf10 and powerOf2 integer variables that you modify with powerOf10 *= 10; powerOf2 *= 2; in each loop iteration.
Try using:
import java.util.Scanner;
public class Test {
public static void main(String[] args) {
Scanner in=new Scanner(System.in);
System.out.print("Enter a binary integer: ");
int b=in.nextInt();
int answer = Integer.parseInt(in.nextInt() + "", 2);
System.out.println("The number is " + answer + ".");
}
}
2 is for base 2.

Calculating factorials with numbers bigger than ints and longs in java?

Been searching here and google for a couple of days as well as asking my programming friends.
Unfortunately, i still don't understand how to change my code...
My program calculates the factorial of a given number. It then provides a number which represents how many digits the factorials answer includes. Then it sums the values of those digits together to give a total.
My program works for any number between 1! and 31!... If you put in anything over 31! (for example 50! or 100!) it doesn't work and just throws back minus numbers and no total.
I was hoping you guys could point me in the right direction or give me some advice.
I understand using BigIntegers maybe a solution however i don't understand them personally, hence coming here.
Any help would be much appreciated. Thanks.
package java20;
/**
* Program to calculate the factorial of a given number.
* Once implemented, it will calculate how many digits the answer includes.
* It will then sum these digits together to provide a total.
* #author shardy
* date: 30/09/2012
*/
//import java.math.BigInteger;
public class Java20 {
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
//Using given number stored in factorialNo, calculates factorial
//currently only works for numbers between 1! and 31! :(
int fact= 1;
int factorialNo = 10;
for (int i = 1; i <= factorialNo; i++)
{
fact=fact*i;
}
System.out.println("The factorial of " + factorialNo +
" (or " + factorialNo + "!) is: " + fact);
//Using answer stored in fact, calculates how many digits the answer has
final int answerNo = fact;
final int digits = 1 + (int)Math.floor(Math.log10(answerNo));
System.out.println("The number of digits in the factorials "
+ "answer is: " + digits);
//Using remainders, calculates each digits value and sums them together
int number = fact;
int reminder;
int sum = 0;
while(number>=1)
{
reminder=number%10;
sum=sum+reminder;
number=number/10;
}
System.out.println("The total sum of all the " + digits
+ " idividual digits from the answer of the factorial of "
+ factorialNo + " is: " + sum);
}
}
You can use BigInteger in java, it has as much numbers as you want
BigInteger fact= BigInteger.ONE;
int factorialNo = 10;
for (int i = 2; i <= factorialNo; i++){
fact = fact.multiply(new BigInteger(String.valueOf(i)));
}
System.out.println("The factorial of " + factorialNo +
" (or " + factorialNo + "!) is: " + fact);
final int digits = fact.toString().length();
BigInteger number = new BigInteger(fact.toString());
BigInteger reminder;
BigInteger sum = BigInteger.ZERO;
BigInteger ten = new BigInteger(String.valueOf(10));
while(number.compareTo(BigInteger.ONE)>=0)
{
reminder=number.mod(ten);
sum=sum.add(reminder);
number=number.divide(ten);
}
System.out.println("The total sum of all the " + digits
+ " idividual digits from the answer of the factorial of "
+ factorialNo + " is: " + sum
EDIT: the code is improved to be compatible with author's code
If you put in anything over 31! (for example 50! or 100!) it doesn't
work and just throws back minus numbers and no total.
This is because primitive integer types are subject to overflow when you exceed their maximum possible value. Which computing factorials has a tendency to do.
I was hoping you guys could point me in the right direction or give me
some advice. I understand using BigIntegers maybe a solution however i
don't understand them personally, hence coming here.
You are correct that using BigInteger is one possible solution. You can, for instance, do something like:
public BigInteger factorial(int num) {
if (num < 0) {
throw new IllegalArgumentException("Not today!");
}
BigInteger result = BigInteger.ONE;
for (int next = 2; next <= num; next++) {
result = result.multiply(new BigInteger(Integer.toString(next, 10)));
}
return result;
}
If you're calculating things like (m!/n!), you are better off using logarithms of factorials.
You should also consider these two improvements:
Memoize, don't recalculate. Store those hard-earned values once you calculate them.
You should be using the gamma function to calculate factorials. The way you're doing it with a loop is the naive thing that is presented to students. There's a nice implementation of ln(gamma(x)) in Numerical Recipes.
You can always use BigDecimal if you must, but it's a last resort. You should still consider these points.
There's a gamma function implementation available from Apache Commons. The source code might not be as familiar as the naive approach, but if you see how it's done it'll be obvious that it's more efficient even for moderate arguments.

Categories