BigInteger Conversion from int to BigInteger - java

I'm having trouble working with BigIntegers. I'm having trouble with the add method in the Rational class. In the Rational(int x, int y) constructor I'm trying to convert the parameters datatype int into the instance variable datatype of BigInteger though the use of thetoString(int n) method.
Am I doing the conversion correctly inside the Rational(int x, int y) constructor?
They way the add method is written I'm getting an error under all of n.num and n.den. I don't understand why I'm getting that error. Am I not correctly using the add method from the BigInteger class?
http://docs.oracle.com/javase/1.4.2/docs/api/java/math/BigInteger.html
Suppose one class has the following
Rational a = new Rational(1,2);
Rational b = new Rational(1,3);
Rational c = new Rational(1,6);
Rational sum = a.add(b).add(c);
println(sum);
and the Rational class includes
import acm.program.*;
import java.math.*;
public class Rational{
public Rational(int x, int y) {
num = new BigInteger(toString(x));
den = new BigInteger(toString(y));
}
public toString(int n) {
return toString(n);
}
public BigInteger add(BigInteger n) {
return new BigInteger(this.num * n.den + n.num * this.den, this.den * n.den)
}
/* private instance variables */
private BigInteger num;
private BigInteger den;
}

To convert an int to BigInteger I would use BigInteger.valueOf(int).
Also, you cannot use operators with BigIntegers, you must use its own methods. Your methos should be like this:
public Rational add(Rational n) {
return new Rational(
this.num.multiply(n.den).add(n.num.multiply(this.den)).intValue(),
this.den.multiply(n.den).intValue());
}

1) Am I doing the conversion correctly inside the Rational(int x, int
y) constructor?
You can use
BigInteger num = BigInteger.valueOf(x);
Making a String first is is not required.
2. They way the add method is written I'm getting an error .....
Your add method is wrong and its not clear what your are trying to acheive in your add method. But if your want to do addition in BigInteger you should use BigInteger#add method and for multiplication between BigInteger you should use BigInteger#multiply method.

A simple error:
public Rational add(Rational n) {
return new Rational(
this.num.multiply(n.den).add(n.num.multiply(this.den)),
this.den.multiply(n.den));
}
Also, when creating a new BigInteger you should use the valueOf(int) method instead of converting to String

To stop the denominators blowing up exponentially, I would use the lowest common multiple of the two denominators as the denominator of the result, not their product. This would look like this.
public Rational add(Rational rhs) {
BigInteger commonFactor = den.gcd(rhs.den);
BigInteger resultNumerator =
num.multiply(rhs.den).add(rhs.num.multiply(den)).divide(commonFactor);
BigInteger resultDenominator = den.multiply(rhs.den).divide(commonFactor);
return new Rational(resultNumerator, resultDenominator);
}
To use this exactly how I've written it, you'll need a new constructor that takes two BigInteger arguments; but you probably want that anyway.

Related

Java constructor with instance methods

over here I have some code that is supposed to make a constructor and some getters for my Fraction class. I'm wondering, is it possible to get both parameters in one getter? Because I'm only supposed to use only one method into obtaining both of my results.
Such as "1/2 and 3/5" for example.
import java.lang.reflect.*; import java.lang.annotation.*; import java.util.*; import java.time.*; // Please do not change or remove this line.
class Fraction {
private Integer nominator;
private Integer denominator;
public Fraction(Integer nominator, Integer denominator){
this.nominator = nominator;
this.denominator = denominator;
}
public Integer getNominator() {
return nominator;
}
public Integer getDenominator() {
return denominator;
}
}
class Main {
public static Fraction createFraction(Integer nominator, Integer denominator) {
return new Fraction(nominator, denominator);
}
public static void main(String[] arguments) {
final Fraction HALF = createFraction(1, 2);
final Fraction THREE_FIFTH = createFraction(3, 5);
System.out.println((HALF));
System.out.println((THREE_FIFTH));
}
public static String toString(Fraction fraction) {
return fraction.getDenominator() + "/" + fraction.getNominator();
}
}
First of all, great that you don't have setters and your class is functionally immutable--good start!
I would somewhat resist getting the nominator and denominator at all. You will eventually have to I'm sure, but try to avoid it.
For instance, if you were multiplying two Fractions you would simply have a Fraction.multiply(Fraction) method that returns a new Fraction, no need for getters. Anything you might want to do to the nominator/denominator you should be able to do inside the Fraction class.
As for if you really NEED to get the values (with one method):
Return a float (do the division internally)
return a string (like your toString method, but in the fraction class)
A string could also look like "7r1" for a value of 15/2.
you COULD return an array but I don't recommend it, cryptic return values are not awesome.
I don't recommend a sub-object either, it would have to have two getters so you aren't really solving any problems here, just kicking it down the line.
I'd consider a getIntegerValue() and getRemainder() but those are two methods--still they are a decent approach.
create a small class and return it or use an array
for example something like this
class Fraction1{
private int nominator;
private int denominator;
}
public Fraction1 getDenominator() {
Fraction1 fr=new Fraction1();
fr.nominator=this.nominator;
fr.denominator=this.denominator;
return fr;
}
..............

Can you implement and override the list.sort() method to sort a list of rational numbers?

So I've been given the following problem:
Write a program that creates a List of Rationals and sorts them into increasing
order. Use appropriate methods from the Collections Framework classes to sort
the elements into increasing order.
I've created a 'Rational' class to represent rational numbers and I've also made the list of random Rational numbers. But I'm having trouble figuring out a way to implement a method of sorting the list. Here's samples of the code before I go on further:
public class Rational implements Comparable<Rational> {
private int num;
private int denom;
private int common;
// Default constructor initialises fields
public Rational() throws IllegalNumDenomException {
setNum(1);
setDenom(2);
}
// Constructor sets fields with given parameters
public Rational(int num, int denom) throws IllegalNumDenomException {
common = gcd(num,denom);
setNum(num/common);
setDenom(denom/common);
}
//Compares two rational numbers
public int compareTo(Rational rhs) {
int tempNumerator = this.getNum() * rhs.getDenom();
int tempNumeratorRhs = rhs.getNum() * this.getDenom();
//Compares rationalised numerators and returns a corresponding value
if (tempNumerator < tempNumeratorRhs) {
return -1;
} else if (tempNumerator > tempNumeratorRhs) {
return 1;
}
return 0;
}
// Overriden toString method
public String toString() {
return num + "/" + denom;
}
//Calculates the GCD of a fraction to simplify it later on
public int gcd(int x, int y) throws IllegalNumDenomException{
while(x != 1){ //Prevents infinite loop as everything is divisible by 1
if(x == y){
return x;
}
else if(x>y){
return gcd(x-y,y);
}
return gcd(x,y/x);
}
return 1;
}
public class RationalList {
public static void main(String[] args) throws IllegalNumDenomException {
List<Rational> rationals = new ArrayList<Rational>();
Random rand = new Random();
int n = rand.nextInt(50) + 1;
//Generates 9 random Rationals
for(int i = 1; i<10; i++){
rationals.add(new Rational(i,n));
n = rand.nextInt(50) + 1;
}
System.out.println("Original Order: " + rationals.toString());
sort(rationals);
System.out.println(rationals);
}
public static List<Rational> sort(List<Rational> rationals){
//Use compareTo method inside a loop until list is sorted
return rationals;
}
Sorry it's a bit long. So my thinking is creating a sort method and using the compareTo method to determine if a Rational is in the correct place, if not swap it. But then I'm unsure if you're able to even move elements around in a list like you can in an array. So I then thought maybe I need to implement the Collections.sort() method and override the sort method but I get to the same problem. Maybe I could use .toArray?
Can anyone shed some light on the way to do this please? Just hints would be useful.
Since you implemented comparable, Collections.sort(rationals) will work.
This is because Collections.sort will work on any List of Comparable things. It has already been designed to use the Comparable.compareTo() method that you have defined, and as long as your compareTo is implemented correctly it should sort your list.
What you are doing is roughly correct.
But then I'm unsure if you're able to even move elements around in a list like you can in an array.
Under the hood, the Collections.sort method can copy the elements of the list into an array, sort the array, and then rebuild the list from the sorted array. The actual behavior depends on the list implementation class.
In the main method of your application you should create a list of Rationals and then use the Collections.sort() method.
You should generate the random list of Rationals and then use Collection.sort(rationalsList);

Why can't I calculate with Number interface?

I wanted to make such class for calculating average value:
public static class AverageValue<T extends Number> {
T data = 0; //ERROR: incompatible types: int cannot be converted to T
int count = 0;
public AverageValue() {}
public AverageValue(T data) {
this.data = data;
count = 1;
}
public void add(T num) {
data+=num; //ERROR: bad operand types for binary operator '+'
count++;
}
public T average() {
return data/(T)count; //ERROR: incompatible types: int cannot be converted to T
}
}
I am not really getting why do we have interface Number if it doesn't abstract number. Because that's what interfaces do - abstract operations with data without holding the data themselves.
The above also makes it clear that you'll probably not be ever able to make your own number implementation (eg. number with unlimited size and precision for some really freaky experimental math programs).
I tried the same with Number instead of generic T with the very same results. Only difference is that Number x = 0 is actually valid.
Is there a way to trick java to compile this or do I have to be a "professional" java programmer and use doubles to calculate averages on byte arrays?
I am not really getting why do we have interface Number if it doesn't abstract number
interface Number does abstract the number for the purposes of storing and converting representations. It does not abstract the number for the purposes of making calculations, because the type of the result representation is not well defined.
The above also makes it clear that you'll probably not be ever able to make your own number implementation (eg. number with unlimited size and precision for some really freaky experimental math programs).
BigDecimal does it without any problem.
Number x = 0 is actually valid.
assigning Integer to Number is OK. Assigning Integer to something that extends Number (say, Double) is not OK. That's why there is a difference.
Is there a way to trick java to compile this or do I have to go full retard professional Java programmer and use doubles to calculate averages on byte arrays?
You need to specify the desired representation of the result when you compute the average. You could abstract it out yourself and supply the "averager" ingerface, but the information about the desired representation needs to get into the method in one way or the other:
interface AverageMaker<T extends Number> {
T initialResult();
T add(T a, Number b);
T divideByCount(T a, int b);
}
public static <T extends Number, R extends Number> R averageValue(Iterable<T> items, AverageMaker<R> maker) {
R res = maker.initialResult();
int count = 0;
for (T val : items) {
res = maker.add(res, val);
count++;
}
return maker.divideByCount(res, count);
}
Define several average makers, like this:
static final AverageMaker<Double> doubleAvg = new AverageMaker<Double>() {
public Double initialResult() { return 0.0; }
public Double add(Double a, Number b) { return a + b.doubleValue(); }
public Double divideByCount(Double a, int b) { return a/b; }
};
static final AverageMaker<Integer> intAvg = new AverageMaker<Integer>() {
public Integer initialResult() { return 0; }
public Integer add(Integer a, Number b) { return a + b.intValue(); }
public Integer divideByCount(Integer a, int b) { return a/b; }
};
Now you can use them in your code together with the averageValue method:
List<Integer> a = new ArrayList<Integer>();
a.add(4);
a.add(8);
a.add(91);
a.add(18);
double avgDouble = averageValue(a, doubleAvg);
int avgInt = averageValue(a, intAvg);
System.out.println(avgDouble); // Prints 30.25
System.out.println(avgInt); // Prints 30
Demo.
You could work with doubles in the class. Since the average of Integers is a Double, this should be correct.
public class AverageValue<T extends Number> {
double data = 0;
int count = 0;
public AverageValue() {
}
public AverageValue(T data) {
this.data = data.doubleValue();
count = 1;
}
public void add(T num) {
data += num.doubleValue();
count++;
}
public double average() {
return data / count;
}
}
This compiles. Usage:
AverageValue<Integer> avgInt = new AverageValue<>();
avgInt.add(1);
avgInt.add(2);
avgInt.add(3);
avgInt.add(4);
System.out.println(avgInt.average());
AverageValue<Double> avgDouble = new AverageValue<>();
avgDouble.add(1.1);
avgDouble.add(1.2);
avgDouble.add(1.3);
avgDouble.add(1.4);
System.out.println(avgDouble.average());
Output:
2.5
1.25
You are mixing up classes (Number) and primitive types (int). Operators like + or \ are not supported for numeric classes (+ is supported for strings, but that's a special case; and unlike e.g. C#, Java does not support custom operator overloading).
A "number with unlimited size and precision for some really freaky experimental math programs" is actually supported with the BigDecimal class, which shows that (and how) you can indeed have your own Number implementation.
ERROR: incompatible types: int cannot be converted to T
T data = (T)(Integer)0;
ERROR: bad operand types for binary operator '+'
ERROR: incompatible types: int cannot be converted to T
in java doesn't exist operator overload Why doesn't Java need Operator Overloading?

Incorrect Casting

For some reason I am getting a precision error when I try to compile my code. The precision error comes in the return of my second method where I am trying to calculate the circumference. What am I doing incorrectly?
public class Methods2
{
public static final double PI = 3.14;
public static double calcCirc(double x)
{
return PI*x;
}
public static int calcCirc(int x)
{
return (2*(double) x)*PI;
}
public static void main(String[]args)
{
System.out.println(calcCirc(10.2));
System.out.println(calcCirc(4));
}
}
You are attempting to return a double value in a method declared to return an int. Java won't let you implicitly narrow your value like that.
If you're okay with the loss of precision, then explicitly cast the value to int -- Java will let you do that.
return (int) ((2*(double) x)*PI);
However, I would change the method to return double instead, not to lose precision:
public static double calcCirc(int x)
... as you already did with your other calcCirc method.
Both versions of calcCirc() ought to return doubles.
Also, side note--consider using different method names since they accept inputs that differ not only in type but also in semantics.
E.g. calcCircFromRadius(double radius), calcCircFromDiameter(double diameter). There's not really a reason to take an int as an input type here since Java will automatically cast ints to doubles for you.
try
public static int calcCirc(int x){
return (int)((2*x)*PI);
}

does this code about arrays make any sense?

I am watching a lecture from the University of California at Berkeley about creating arrays in Java. The professor presents the following code, and claims the code will create fractions such as 1/6, 2/6, etc. (I added main() so it can be tested.)
public class Test {
public static void main(String[] args) {
Fraction[] f = new Fraction[5];
for (int i=0; i<5; i++){
f[i] = new Fraction(i, 6);
}
}
}
I am testing this in Eclipse, obviously the code does not compile since there is no class Fraction, and even if I change Fraction to double the code still will not produce any fractions.
I am guessing the professor intended to write this:
public class Test {
public static void main(String[] args) {
double[] f = new double[5];
for (int i=0; i<5; i++){
f[i] = (i/6);
}
}
}
Is my reasoning correct?
Source: https://www.youtube.com/watch?v=wGibp2L5uCc #12:25
First of all, note that this will start at 0/6, not 1/6. Second of all, the professor is most probably referring to a hypothetical Fraction class that stores exact fractions (i.e. a numerator and a denominator as two ints); a double cannot do this.
Now, if you want to use doubles (which will not store exact fractions per se but rather the approximate numbers they represent), you have to use double division (and not integer division, as you are currently performing):
f[i] = i/6.0;
As #StephenTG points out, the Fraction class seems to be implemented here.
Yes and no. This:
f[i] = new Fraction(i, 6);
Means
Store on position i of the f array, this fraction object
f is a Fraction[], meaning that each index contains a Fraction typed object. You need to create a new one (i.e. new Ftaction(1,6)) in order to store 1/6. You were right about what to store, you just were not getting the whole picture about how do you represent it.
Just for the sake of your class, I assume that Fraction is a type created by your teacher and that you have to include in your project (As others have correctly suggested, you might be searching for this class)
There is fraction class here:
http://www.cs.berkeley.edu/~jrs/61bf98/labs/lab2/Fraction.java
I assume this is part of your class as well.
You have to download this file and add it to your project.
Well, if the Fraction class has a method to return a double or a float, it can be very well constructed with int actually.
Then the internal logics will take care of processing and returning the correct type.
Consider this example:
public static void main(String[] args) {
System.out.println(new Fraction(1, 6).getFraction());
}
static class Fraction {
private float fraction;
public Fraction(int num, int den) {
// TODO check that den != 0, otherwise we're in a world of trouble :D
fraction = (float) num/den;
}
public float getFraction() {
return fraction;
}
}
Output:
0.16666667
You need to create the Fraction class in order to create an array of Fraction objects.
From StephenTG's comment, it looks like you need to import Fraction.java into eclipse.
(This Fraction.java has a main method for testing purposes. You can place your code in that method, or you need to remove that method if you want to use your own main method.)
You should define a Fraction class first:
public class Fraction
{
int numerator;
int denominator;
public Fraction(){}
/* watch out for a division by zero Exception!
* maybe throw a custom exception here
*/
public Fraction(int n, int d){
numerator = n;
denominator = d;
}
public float getValue(){
return numerator * 1.0f/denominator;
}
}
your first snippet will only make sense if your Fraction class has a constructor that takes two integer values (e.g.):
class Fraction
{
private int val1, val2;
public Fraction(int val1, int val2)
{
this.val1 = val1;
this.val2 = val2;
}
}
For your second part of the question, your loop will first return an integer and then type-cast it to double. So, the result in your case will always be zero, even though you know it shouldn't. To fix this, any of the following two lines of code will do.
f[i] = ((i + 0.0)/6);
or
f[i] = (i/6.0);

Categories