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);
Related
I recently started to learn about generics in Java, and I understand the basic concepts of generics. However, one thing I don't understand is that I don't know why the following method doesn't work:
public class Generics<T extends Number> {
T num;
Generics(T n){
num = n;
}
//...
T timesTwo() { //Return the value that's twice as much as 'num'
return num * 2;
}
}
It was my first approach, and I kind of understand why it is not working. The error message said: The operator * is undefined for the argument types(s) T, int.
I guess Java couldn't multiply the T and int type together. (But shouldn't the compiler be able to auto-unbox T since it's involved in an expression AND the class extends Number?)
So I gave up on this method and tried to replace it with this method:
T times(T i) { //This method was supposed to receive another T object as
//an argument and multiply them together, then return the output
return num * i;
}
But once again, the exact same error message appeared (the only change was that int was replaced by T).
Why is the code not working, and how can I fix it?
I agree with the first two comments. Also, it's not a generics problem, it's just that the method doesn't work because it's not supposed to work because the boxing assumption you concluded doesn't apply here.
Autoboxing and Unboxing are supplied for some of the Number types but not all. See table below: https://docs.oracle.com/javase/tutorial/java/data/autoboxing.html
So while this works the way you expect (because both types are in the supported table):
public static void main(String[] args) {
Integer a = 3;
Integer b = 2;
Number answer = a * b;
System.out.println("Answer: " + answer);
}
This intuitively equivalent code will NOT work:
public static void main(String[] args) {
Number a = 3;
Number b = 2;
Number answer = a * b;
System.out.println("Answer: " + answer);
}
In fact, from the Compiler's perspective, it gives you the same cross-eyed look you would get if you tried this:
public static void main(String[] args) {
String a = "what does it even mean to multiply a string with a number..??";
Byte b = 2;
Number answer = a * b;
System.out.println("Answer: " + answer);
}
So to finish the point, from the compiler's perspective, since auto-boxing does not apply, it's just as confused as to how to multiply two Numbers as it is how to multiply two other random objects like a String and a Byte and reports the error accordingly
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;
}
..............
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);
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.
So, I created a simple class named Test, as follows:
import prog.utili.IntegerB;
//It's a custom class
class Test
{
public static void main(String[] args)
{
IntegerB a = new IntegerB(1);
IntegerB b = new IntegerB(2);
IntegerB sum = a.plus(b);
System.out.println(sum);
}
}
I wanted to practise with inheritance so I created two custom classes. Fraction...
package prog.utili;
public class Fraction
{
private int num;
private int den;
public Fraction(int x, int y)
{
[...]
}
public Fraction(int x)
{
this(x, 1);
}
public Fraction plus(Fraction f)
{
int n = this.num * f.den + this.den * f.num;
int d = this.den * f.den;
return new Fraction(n, d);
}
[...]
}
...and IntegerB:
package prog.utili;
public class IntegerB extends Fraction
{
public IntegerB(int num)
{
super(num);
}
public IntegerB plus(IntegerB other)
{
return (IntegerB)this.plus(other);
}
}
The problem is I keep getting the same error:
at prog.utili.IntegerB.plus(IntegerB.java:11)
I know I could simply solve the problem by just deleting the last method on IntegerB and replacing the 9th line of Test.java with
IntegerB sum = (IntegerB)a.plus(b)
but I absolutely want to do it using the inheritance rules over the "plus" method!
To implement the method plus(IntegerB), you call plus(IntegerB), which calls plus(IntegerB), etc. etc. until you get a StackOverflowError.
Provide an actual implementation for your method:
return new IntegerB(this.getNum() + other.getNum());
or
return new IntegerB(super.plus(other).getNum());
Also note that replacing the last line of Test.java by
IntegerB sum = (IntegerB)a.plus(b);
wouldn't work, since the plus() method in Fraction doesn't return an IntegerB, but a Fraction. You would thus get a ClassCastException.
The problem here is that IntegerB.plus does not override Fraction.plus, it overloads it. This is because the argument types are different. Thus when IntegerB.plus calls this.plus(other), it ends up calling itself, which then calls itself, which then calls itself until you get a StackOverflow (thus sending you to stackoverflow : )).
It seems like you want to call plus(Fraction) instead of plus(IntegerB). To do that, you can explicitly upcast other:
return plus((Fraction) other);
This cast has no effect other than to tell the compiler that you want to call the version of plus that handles Fractions, even though you know you have an IntegerB.
However, this method would not return an IntegerB, but just a Fraction whose denominator is 1. You could conceivably override plus to return an IntegerB if the denominator of the result is 1, but that might lead to unexpected situations where a.plus(b) is not equal to b.plus(a) because one is a Fraction while the other is an IntegerB. Alternatively, you could return IntegerB objects from Fraction.plus when possible.