about Java BigInteger - java

I'm new to Java and just code a program with BigInteger.
public static void main(String[] args) {
BigInteger n = new BigInteger("5");
BigInteger i = new BigInteger("2");
while (lesserOrEqual(i,n) {
System.out.println("n.mod(i) = "+n.mod(i));
if (n.mod(i) == ZERO) {
n = n.divide(i);
}
else {
i.add(ONE);
}
System.out.println("n = "+n);
System.out.println("i = "+i);
}
public static boolean lesserOrEqual(BigInteger m, BigInteger n) `{
if (m.compareTo(n) == -1 || m.compareTo(n) == 0)
return true;
return false;
}
ZERO and ONE are defined of the type BigInteger 0, 1, respectively.
I want "i=2" to divide "n=5", if "n mod i == 0", else "i++", until "n" to be lesser or equal to "i".
I think the output must be
n.mod(i) = 1
n = 5
i = 3
n.mod(i) = 2
n = 5
i = 4
n.mod(i) = 1
n = 5
i = 5
n.mod(i) = 0
n = 1
i = 5
and with the equivalent code with primitive type int, I have the result as expected.
but this with BigInteger goes to infinite loop
n.mod(i) = 1
n = 5
i = 2
...
Does anyone know why it is so?

The BigInteger class represents integers as immutable objects.
There are two points here.
Don't use == to test if two BigIntegers are equal
To change the value of a BigInteger variable you must do i = i.add(ONE); and not just i.add(ONE);.
The reason not to use == to compare BigIntegers is because instead of checking for numerical equality you are checking that they are the same object in memory.
Consider with Strings.
String a = "a";
String b = "b";
String x = a + b;
String y = "ab";
In the above example x.equals(y) is true because they contain the same number of characters in exactly the same order. However, x == y is not true because they are different objects in memory.
The reason you need to to assign the result of arithmetic operations to a variable is because BigInteger is immutable. Thus arithmetic operations cannot change the value of the object it is operating on, but it can create a new BigInteger (which it returns). Which is why you must assign the result of the arithmetic operation to the variable you want it saved in.
As an aside a shortcut for your lesserThanOrEqual to is this.
boolean result = m.compareTo(n) <= 0;
Basically
m == n becomes m.compareTo(n) == 0
m != n becomes m.compareTo(n) != 0
m < n becomes m.compareTo(n) < 0
m > n becomes m.compareTo(n) > 0
m <= n becomes m.compareTo(n) <= 0
m >= n becomes m.compareTo(n) >= 0

both of the above answers are right. They are not telling you, however, that BigInteger instances are immutable. That means they don't change once set. That is why you need to always assign the result of a transformation...

You are doing this:
i.add(ONE);
But you should do this:
i = i.add(ONE);

You're not saving the result that gets returned from i.add(ONE). It's giving you a BigInteger object containing the desired value, but you're dropping it on the floor instead of assigning it to i.

i.add(ONE) has to be reassigned: i = i.add(ONE)

Related

Decrement NaturalNumber using recursion question

I do not understand why the recursion problem of this code I wrote works, below I will show what the function that is used in the code below from the library used in my university
void multiplyBy10(int k)
Multiplies this by 10 and adds k.
Parameters:
k - the int to be added
Updates:
this
Requires:
0 <= k < 10
Ensures:
this = 10 * #this + k
and divideBy10 simply divides the natural number by 10 and returns the remainder and NaturalNumber.RADIX is simply a constant equal to 10.
private static void decrement(NaturalNumber n) {
assert n != null : "Violation of: n is not null";
assert !n.isZero() : "Violation of: n > 0";
int digit = n.divideBy10();
digit = digit - 1;
if (digit == NaturalNumber.RADIX) {
digit = 0;
decrement(n);
} else if (digit < 0) {
digit = 9;
decrement(n);
}
n.multiplyBy10(digit);
}
Now the code does work, if you input any number it will decrease it by 1, although I am a bit confused as to why
First of all. Thats exactly the reason why classes like NaturalNumber should be immutable. Using a static method for applying changes on an instance is a violation of the open-closed-principle.
'int digit = n.divideBy10();' changes the value of n. Otherwise this method would not terminate.
I assume that you call 'n.multiplyBy10(-1)'. This would explain the correct result for numbers<10.
Which input arguments have you tested for this method?

Write a program in java to print the sum of all numbers from 50 to 250(inclusive of 50 and 250) that are multiples of 3 and not divisible by 9

/* when I run this code there is no error in fact output generated is also correct but I want to know what is the logical error in this code? please can any one explain what is the logical error. */
class abc
{
public static void main(String arg[]){
int sum=0;
//for-loop for numbers 50-250
for(int i=50;i<251;i++){
// condition to check if number should be divided by 3 and not divided by 9
if(i%3==0 & i%9!=0){
//individual number which are selected in loop
System.out.println(i);
//adding values of array so that total sum can be calculated
sum=sum+i;
}
}
//final display output for the code
System.out.println("the sum of intergers from 50 to 250 that are multiples of 3 and not divisible by 9 \n"+sum);
}
}
My philosophy is "less code == less bugs":
int sum = IntStream.rangeClosed(50, 250)
.filter(i -> i % 3 == 0)
.filter(i -> i % 9 != 0)
.sum();
One line. Easy to read and understand. No bugs.
Change this:
if(i%3==0 & i%9!=0){
to this:
if(i%3==0 && i%9!=0){
& = bitwise and operator
&& = logical operator
Difference between & and && in Java?
The only problems I saw were:
The variable sum was undeclared
Use && in place of &
int sum = 0;
for (int i = 50; i <= 250; i++) {
if (i % 3 == 0 && i % 9 != 0) {
System.out.println(i);
sum = sum + i;
}
}
System.out.println("the sum of intergers from 50 to 250 that are multiples of 3 and not divisible by 9 \n" + sum);
Well, instead of touching every single value from 50 to 250 like you would do here for(int i=50;i<251;i++), you can consider something like this...
int i = 48;
int sum = 0;
while(i < 250) {
i += 3;
if(i%9 != 0)
sum += i;
}
This is somewhat optimized in the sense that I am skipping over values that I know are not possible candidates.
But, there is a much bigger issue in your code. The following code block prints true, sure. But, it is a bad idea to depend on the & since that is not its job. The & is for bitwise AND whereas the && is for logical AND, which is what you are trying to do.
boolean t = true;
boolean f = false;
System.out.println(f&t);
Why?
In Java, if it is a && operation, as soon as you find the first false, you are sure that the expression will evaluate to false. Meanwhile, in your implementation, it would need to evaluate both sides. f&t will evaluate to false, but the JVM would need to look at both the f and t variables. Meanwhile, on using &&, it wouldn't even need to look at the t.

Greatest common divisor

I try to find the greatest common divisor for two integers. But I don't understand what is wrong with my code:
public class Main {
public static void main(String[] args) {
Scanner s = new Scanner(System.in);
int a = s.nextInt();
int b = s.nextInt();
while (a != 0 | b != 0) {
if (a >= b) {
a = a % b;
} else {
b = b % a;
}
}
if (a == 0) {
System.out.println(b);
} else {
System.out.println(a);
}
}
}
Just change
a != 0 | b != 0
to
a != 0 && b != 0
Because you version will be work even a or b equals 0.
But you need to exit from loop when one of them equals 0.
&& - better than & because in your case you don't need to check
right-hand operator if left equals 0
It is easier to calculate the GCD if we understand the core logic. Try to understand what we need to do, and how we are going to do it before implementing the program.
What we are trying to find is the greatest number that divides both a and b.
So the question arises that how we are going to do it. We do a loop just like you did, but for this case, let's initially assume that a is greater than b.
The first step is to start the loop, while the calculation is not finished. The condition in our case is, we have to stop when any one of the two numbers becomes zero.
while (a != 0 && b != 0)
{
// Do the calculation here.
}
Now we have to write the calculation. We have assumed that a is greater than b or both are equal.
We keep on assigning the remainder of a divided by b to a.
while (a != 0 && b != 0)
{
a = a % b;
}
This makes the solution only half correct, we will have to deal with the other case, that is when b is greater than a. Why this happens is after some set of iterations, a will become less than b, and that will result in a being set to 0.
So let's do the same solution to the other case, when a is less than b.
while (a != 0 && b != 0)
{
if (a > b)
a = a % b;
else
b = b % a;
}
And this is what you wanted to achieve. The non-zero value will be the solution.
Let's just not stop here, and see why your current version does not work. You have had this in your condition.
Your condition is:
a != 0 | b != 0
Here, you are using bit-wise operator OR, between two boolean values, which comes to the following. Assume any of a and b is zero.
Case 1:
a != 0 => true
b != 0 => false
true | false => true
Case 2:
a != 0 => false
b != 0 => true
false | true => true
Therefore as you see in the above cases, it continues to loop until both becomes zero, and hence you will always be reported as the GCD is zero.
Hope this helps.
You probably need to implement the Eudidean's Algorithm (which is actually about the math) But here is an example of how does this alg works
private static int GCD(int a, int b)
{
int remainder = a % b;
while (remainder!= 0)
{
a = b;
b = remainder;
remainder = a % b;
}
return b;
}

Converting int to string in java is giving the answer as 1

I converted a decimal integer to binary and that binary integer when I'm trying to convert to a string is giving me 1 as the answer always when it should give the value of the string.
while(a>0)
{
b = a%2;
n = b;
a = a/2;
System.out.print(n);
}
String m = Integer.toString(n);
System.out.print(m);
Any corrections and suggestions would be much appreciated.
Thanks!
On every loop step, you have these two statements:
b = a % 2;
n = b;
Think about why all the possible values of n are 0 and 1?
It's because n copies the value of b, which is the value of a modulo 2, which is always 0 or 1.
The last value of n will be the left-most bit of the binary representation of a, which will be always 1 (unless a is 0) and this is why you always get 1 when printing m.
When you use
n = b;
you are replacing the value of n each time. What you want it to accumulate the bits in n. The simplest way to do this is to use a StringBuilder.
StringBuilder sb = new StringBuilder();
while (a > 0) {
int lowest = a & 1;
sb.insert(0, lowest);
a = a >>> 1; // shift the bits down by 1.
}
String m = sb.toString();
System.out.print(m);
This will do the same thing as Integer.toString(a, 2)

The method returns true if the integer is divisible by 3 and returns false if the integer is not divisible by 3

This is what I have so far; I have to use this main method.
public class HW4 {
public static boolean isDivisibleByThree(String n) {
int sum = 0;
int value;
for (int k = 0; k < n.length(); k++) {
char ch = n.charAt(k);
value = Character.getNumericValue(ch);
sum = sum*value;
}
return sum*3 == 0;
}
}
It always comes out true and I'm really stuck in this part. So if you can, can you help me out?
A sum is a cumulative addition (not multiplication).
Change this line:
sum = sum * value;
To
sum = sum + value;
Or the more brief version:
sum += value;
Much easier solution: use the mod-function:
int number = int.Parse(input);
bool result = (number % 3 == 0);
Two things:
sum = sum * value? This should probably be sum = sum + value, or short sum += value
sum * 3 == 0 should probably be sum % 3 == 0
If you are required to not use the % operator, you could alternatively do:
double check = (double)sum / 3.0;
return check == (int)check;
The problem with negative numbers is that the - gets parsed too, you could sove it by dropping it:
if (n[0] == '-') {
n = n.substring(1);
}
This drops the sign if it is negative and does nothing otherwise.
Unless I'm missing something, you would first use Integer.parseInt(String) to parse the int from the String. Then you can divide that value by 3 using integer division. Finally, test if that number multiplied by 3 is the original value.
int value = Integer.parseInt(n);
int third = value / 3;
return (value == third * 3);

Categories

Resources