0

Im trying to create a program for the collatz conjecture, and I need it to work for bigger numbers. So, i tried to use the BigInteger class, but it seems to run into an error with the two types: bigint and int.

I've looked up the problems for big int, and it seemingly works with the addition and multiplication. However, when trying to get the remainder when dividing by two, it returns an error. (At the start of runtime).

import java.math.BigInteger;
import java.math.Bigdecimal;
import java.util.Objects;
import java.util.Scanner;
public class Main {
    /**
     * @param args
     */
    public static void main(String[] args) {
        boolean repeat = true;
        while (repeat){
            int i = 0;
            Scanner intIn = new Scanner(System.in);
            Scanner strIn = new Scanner(System.in);
            System.out.println("Enter number you want solved, Don't type 0. Use this program with caution");
            BigInteger num = intIn.nextBigInteger();
            while (num.equals(new BigInteger("1")) == false){
                if (num.equals(new BigInteger("1"))){
                  // The issue currently is that the remainder function returns an error, but im not sure exactly what is wrong with it.
                } else if (num.remainder(new BigInteger("2")) == 0) {
                    num = num.divide(new BigInteger("2"));
                } else {
                    num = num.multiply(new BigInteger("3"));
                    num = num.add(new BigInteger("1"));
                }
                i += 1;
            }
            System.out.println("It took " + i + " steps to reach 1. Would you like to do another number? (yes/no)");
            String yn = strIn.nextLine();
            if (Objects.equals(yn, "no")){
                repeat = false;
            }
        }
    }
}

In line 21, the error is with the remainder function. (in case you missed the comment)

bobby
  • 13
  • 2
  • 1
    "checking to see if it is equal" -> method `equals()` ( `not()` is bitwise complement and does not take any argument) – user16320675 Apr 30 '23 at 06:06
  • 1
    [Please do not upload images of code/data/errors.](//meta.stackoverflow.com/q/285551) – Sören Apr 30 '23 at 06:53
  • 1
    (1) Don't use two Scanners. You only need one, and two won't work. (2) You can't compare `BigIntegers` to primitve types. Use `BigInteger.equals()`, as already mentioned. – user207421 Apr 30 '23 at 07:33
  • 1
    `java.lang.Error: Unresolved compilation problem` - This implies that you tried to run some code before fixing the compilation errors. Don't do that. Fix the compilation errors first. If you do it your way, you need to scratch your head to figure out where the compilation errors actually are!! – Stephen C Apr 30 '23 at 07:50
  • 2
    https://stackoverflow.com/questions/55791203 is related. The same applies to the relational operators involving primitive operands; i.e. `==`, `!=`, `<`, `<=`, `>` and `>=` the unary operators `+`, `-` and `~` and the bitwise and shift operators. The only operators that will work are `==` and `!=` for other (compatible) reference types. – Stephen C Apr 30 '23 at 07:58
  • @xerx593 Neither of those is illegal syntax. Neither of those is illegal at all. In the first example, if `someObject` is `Double`, `Float`, `Byte`, `Short`, `Integer`, or `Long`, the expression is legal semantically, and it is always legal syntactically. If you think otherwise please produce where in the Java Language Specification it says so. – user207421 Apr 30 '23 at 11:12
  • 1
    "In line 21, the error is with the remainder function. (in case you missed the comment)" people should not need to read comments, you should edit your question to add all relevant information and make it as self-contained as possible. Also include the errors in the questions. And note that there are no line numbers so you should also show the specific line with the specific error. – aled Apr 30 '23 at 12:35
  • @xerx593 Yes, it is legal syntax. That is a *semantic* error. If it had been illegal syntax you would have got the message 'syntax error'. – user207421 Apr 30 '23 at 23:50

1 Answers1

0

The problem is that num.remainder(new BigInteger("2")) returns another BigInteger and you try to compare that BigInteger with an int value (0).

The Java Language Specification 15.21. Equality Operators states:

The equality operators may be used to compare two operands that are convertible (§5.1.8) to numeric type, or two operands of type boolean or Boolean, or two operands that are each of either reference type or the null type. All other cases result in a compile-time error.

(There is an additional constraint for equality operators on reference types, see the last block).

Since BigInteger is a reference type that is not convertible to a numeric type (5.1.8. Unboxing Conversion mentions that only Byte, Short, Character, Integer, Long, Float and Double are) the last clause (all other cases result in a compile-time error) applies.

To fix it change the comparison to

num.remainder(new BigInteger("2")).equals(BigInteger.ZERO)

Note that the BigInteger class has some helpful constants for your code:

BigInteger.ZERO
BigInteger.ONE
BigInteger.TWO

Your loop makes repeated use of these values and therefore will run faster if you use these constants instead of repeatedly creating new BigInteger objects for them.

IMHO you should even consider creating another local constant for the value three:

BigInteger THREE = BigInteger.valueOf(3);

and use it for example in

num.multiply(THREE)

One more note:

num.equals(new BigInteger("1")) == false

looks weird and can be written shorter as

!num.equals(BigInteger.ONE)

One last note (already mentioned in the comments):

Use only one Scanner for all the input. Using two scanners might seem to work in your simple case, but will fail in others (for example when using input redirection).

Using only one scanner can lead to other problems as can be seen in Scanner is skipping nextLine() after using next() or nextFoo()?, but it is still the correct way to do.


There is an additional condition for equality comparison of reference types mentioned in 15.21.3. Reference Equality Operators == and !=

It is a compile-time error if it is impossible to convert the type of either operand to the type of the other by a casting conversion (§5.5). The run-time values of the two operands would necessarily be unequal (ignoring the case where both values are null).

Thomas Kläger
  • 17,754
  • 3
  • 23
  • 34