I have to sort an array of fractions here is my code for the class which is working fine.
public class Fraction implements Comparable<Fraction>{
private int numerator;
private int denominator;
public Fraction(int num, int den){
numerator = num;
denominator = den;
}
public int compareTo(Fraction fraction){
if(decimalValue()>fraction.decimalValue()){
return 1;
}else if(decimalValue()<fraction.decimalValue()){
return -1;
}else{
return 0;
}
}
public Fraction reduce(int numerator, int denominator){
if(numerator==0&&denominator==0){
numerator = 0;
denominator = 0;
}
else{
for(int x = Math.min(Math.abs(numerator), Math.abs(denominator)); x>0; x--){
if(denominator == numerator){
numerator = 1;
denominator = 1;
}
else if(numerator == 0){
numerator = 0;
denominator = 1;
}
else if(numerator%x==0 && denominator%x==0){
numerator = numerator/x;
denominator = denominator/x;
}
}
}
public double decimalValue(){
double decimal = (numerator*1.0)/(1.0*denominator);
return decimal;
}
public String toString(){
reduce(numerator, denominator);
return ((numerator) + "/" + (denominator));
}
}
For some reason the sort() is not working if I used it with a comparator like in the answer it works but I don't understand why this doesn't work. Here is the tester:
public class FractionChecker{
public static void main (String[]args){
int n, d;
Random rand = new Random();
Fraction[] f = new Fraction [20];
for (int j= 0; j<20; j++){
n = rand.nextInt(20);
d = rand.nextInt(19)+1;
f[j] = new Fraction (n,d);
}
System.out.println("Unsorted " + Arrays.toString(f));
Arrays.sort(f);
}
}
Error:
----jGRASP exec: java FractionChecker
Unsorted [7/6, 15/14, 5/15, 8/9, 19/16, 16/5, 11/16, 2/9, 11/10, 10/12, 12/11, 9/18, 15/4, 11/4, 10/7, 12/8, 13/14, 19/5, 19/15, 13/5]
Exception in thread "main" java.lang.ClassCastException: Fraction cannot be cast to java.lang.Comparable
at java.util.Arrays.mergeSort(Arrays.java:1144)
at java.util.Arrays.mergeSort(Arrays.java:1155)
at java.util.Arrays.mergeSort(Arrays.java:1155)
at java.util.Arrays.sort(Arrays.java:1079)
at FractionChecker.main(FractionChecker.java:18)
----jGRASP wedge: exit code for process is 1.
----jGRASP: operation complete.
This is the error I am getting when I use Arrays.sort(f) and I am not sure why.
Collections.sort expects a List whose type implements Comparable. You're providing an array of Fraction objects instead.
You should use Arrays.sort instead:
Arrays.sort(f);
If the above throws a ClassCastException for some reason, you can try this version of Arrays.sort, which requires a Comparator as an argument that will do the comparing:
Arrays.sort(f, new java.util.Comparator<Fraction>() {
#Override
public int compare(Fraction f1, Fraction f2) {
return f1.compareTo(f2);
}
});
I don't see your decimalValue code. A better way to compare fractions in any case may be:
long left = numerator * other.denominator;
long right = other.numerator * denominator;
if (left == right) {
return 0;
} else if (left < right) {
return -1;
} else /* if (left > right) */ {
return 1;
}
Not that this will increase your performance drastically but it is just neater and handles division by zero in a sensible way.
The code below works and prints success
import java.util.Arrays;
public class Fraction implements Comparable<Fraction>{
private int numerator;
private int denominator;
public Fraction(int num, int den){
numerator = num;
denominator = den;
}
public int compareTo(Fraction fraction){
if(decimalValue()>fraction.decimalValue()){
return 1;
}else if(decimalValue()<fraction.decimalValue()){
return -1;
}else{
return 0;
}
}
public double decimalValue(){
double decimal = (numerator*1.0)/(1.0*denominator);
return decimal;
}
public String toString(){
return ((numerator) + "/" + (denominator));
}
public static void main(String[] a) {
Fraction[] fractions = new Fraction[2];
fractions[0] = new Fraction(1,1);
fractions[1] = new Fraction(2,3);
Arrays.sort(fractions);
System.out.println("success");
}
}
Related
I have a class definition for a class of rational numbers. My assignment is to be able to add, multiply and divide any fraction I put in my main function. My program can do all that, but I'm having trouble simplifying the fractions. I want to try and use only two methods to simplify, for example public void reduce(); and private static gcd();
public class Rational {
private int num;
private int denom;
public Rational() {
num = 0;
denom = 1;
}
public Rational(int n, int d) {
num = n;
denom = d;
reduce();
}
public Rational plus(Rational t) {
int tnum = 0;
int tdenom = 1;
tnum = (this.num * t.denom) + (this.denom * t.num);
tdenom = (t.denom * this.denom);
Rational r = new Rational (tnum, tdenom);
return r;
}
public Rational minus(Rational t) {
int tnum = 0;
int tdenom = 1;
tnum = (this.num * t.denom) - (this.denom * t.num);
tdenom = (t.denom * this.denom);
Rational r = new Rational (tnum, tdenom);
return r;
}
public Rational multiply(Rational t) {
int tnum = 0;
int tdenom = 1;
tnum = this.num * t.num;
tdenom = t.denom * this.denom;
Rational r = new Rational (tnum, tdenom);
return r;
}
public Rational divide(Rational t) {
int tnum = 0;
int tdenom = 1;
tnum = this.num / t.num;
tdenom = this.denom / t.denom;
Rational r = new Rational (tnum, tdenom);
return r;
}
private static int gcd(int n, int d) {
return gcd(d, n%d);
}
public void reduce() {
//call gcd
gcd(num, denom);
//divide num and denom by gcd by
num = num / gcd(num,denom);
denom = denom / gcd(num,denom);
}
public String toString() {
return String.format("%d/%d", num, denom);
}
}
public class RationalMain {
public static void main(String[] args) {
Rational x = new Rational();
Rational y = new Rational(1,4);
Rational z = new Rational(1,2);
//x = y - z;
x = y.plus(z);
System.out.printf("%s = %s + %s\n", x.toString(), y.toString(), z.toString());
x = z.minus(y);
System.out.printf("%s = %s - %s\n", x.toString(), z.toString(), y.toString());
x = z.multiply(y);
System.out.printf("%s = %s * %s\n", x.toString(), z.toString(), y.toString());
x = y.divide(z);
System.out.printf("%s = %s / %s\n", x.toString(), y.toString(), z.toString());
}
}
That's not how you might achieve the Greatest Common Divisor (GCD). Before you will be able to get your code to work properly you will need to at least fix your gcd() method since currently it will recurse until an ArithmeticException (/ by zero) is generated. You might achieve the task this way:
private static int gcd(int num, int den) {
num = Math.abs(num); // if numerator is signed convert to unsigned.
int gcd = Math.abs(den); // if denominator is signed convert to unsigned.
int temp = num % gcd;
while (temp > 0) {
num = gcd;
gcd = temp;
temp = num % gcd;
}
return gcd;
}
To convert your fractions too their Lowest Terms your reduce() method might look like this if it accepted a Fraction String as an argument (you modify the method parameters if you like):
/*
A Fraction String can be supplied as: "1/2", or "2 1/2", or
"2-1/2, or "-2 32/64", or "-2-32/64". The last 2 examples are
negative fraction values.
*/
private String reduce(String fractionString) {
// Fraction can be supplied as: "1/2", or "2 1/2", or "2-1/2".
// Make sure it's a Fraction String that was supplied as argument...
inputString = inputString.replaceAll("\\s+", " ").trim();
if (!inputString.matches("\\d+\\/\\d+|\\d+\\s+\\d+\\/\\d+|\\d+\\-\\d+\\/\\d+")) {
return null;
}
str2 = new StringBuilder();
String wholeNumber, actualFraction;
if (inputString.contains(" ")) {
wholeNumber = inputString.substring(0, inputString.indexOf(" "));
actualFraction = inputString.substring(inputString.indexOf(" ") + 1);
str2.append(wholeNumber);
str2.append(" ");
}
else if (inputString.contains("-")) {
wholeNumber = inputString.substring(0, inputString.indexOf("-"));
actualFraction = inputString.substring(inputString.indexOf("-") + 1);
str2.append(wholeNumber);
str2.append("-");
}
else {
actualFraction = inputString;
}
String[] tfltParts = actualFraction.split("\\/");
int tfltNumerator = Integer.parseInt(tfltParts[0]);
int tfltDenominator = Integer.parseInt(tfltParts[1]);
// find the larger of the numerator and denominator
int tfltN = tfltNumerator;
int tfltD = tfltDenominator;
int tfltLargest;
if (tfltNumerator < 0) {
tfltN = -tfltNumerator;
}
if (tfltN > tfltD) {
tfltLargest = tfltN;
}
else {
tfltLargest = tfltD;
}
// Find the largest number that divides the numerator and
// denominator evenly
int tfltGCD = 0;
for (int tlftI = tfltLargest; tlftI >= 2; tlftI--) {
if (tfltNumerator % tlftI == 0 && tfltDenominator % tlftI == 0) {
tfltGCD = tlftI;
break;
}
}
// Divide the largest common denominator out of numerator, denominator
if (tfltGCD != 0) {
tfltNumerator /= tfltGCD;
tfltDenominator /= tfltGCD;
}
str2.append(String.valueOf(tfltNumerator)).append("/").append(String.valueOf(tfltDenominator));
return str2.toString();
}
As you can see, a whole number can also be supplied with your fraction so, if you do a call to the above reduce() method like this:
System.out.println(reduce("12-32/64"));
System.out.println(reduce("12 32/64"));
The console window will display:
12-1/2
12 1/2
Please explain how to implement main method. i am having trouble with the main method and the line after main method, why the line after main method showing illegal start of expression?? is it because i forgot to put bracket somewhere or my code is wrong?? the code is suppose to perform arithmetic with fraction.
public class Rational{
public static void main(String [] args){
public int numerator;
public int denominator;
public Rational(int numerator, int denominator)
{
this.numerator = numerator;
this.denominator = denominator;
reduce();
}
public Rational add(Rational other)
{
int num = numerator * other.denominator + other.numerator * denominator;
int den = denominator * other.denominator;
return new Rational(num, den);
}
public Rational subtract(Rational other)
{
int num = numerator * other.denominator - other.numerator * denominator;
int den = denominator * other.denominator;
return new Rational(num, den);
}
public Rational multiply(Rational other)
{
int num = numerator * other.numerator;
int den = denominator * other.denominator;
return new Rational(num, den);
}
public Rational divide(Rational other)
{
int num = numerator * other.denominator;
int den = denominator * other.numerator;
return new Rational(num, den);
}
private void reduce()
{
int min = 0;
if(numerator > denominator)
{
min = denominator;
}
else
{
min = numerator;
}
for(int i = min; i > 1; i--)
{
boolean isNumDiv = numerator % i == 0;
boolean isDenDiv = denominator % i == 0;
if(isNumDiv && isDenDiv)
{
numerator = numerator / i;
denominator = denominator / i;
break;
}
}
}
public String toString()
{
return numerator + " / " + denominator;
}
} }
Suppose you have to create a program that prints a sum. You can create a file Sum.java with the Sum class inside it. Like this:
public class Sum {
public int x;
public int y;
public Sum(int x, int y) {
this.x = x;
this.y = y;
}
public int sumMyNumbers() {
return x + y;
}
}
Now you can create a file named Main.java with your Main class that will be the entry point of your program and it could be like this:
public class Main {
public static void main(String[] args) {
// It will print the number 4 on your console
System.out.println(new Sum(2, 2).sumMyNumbers());
// Or like this:
Sum mySum = new Sum(2,2);
System.out.println(mySum.sumMyNumbers());
// Or even like this:
int i = new Sum(2, 2).sumMyNumbers();
System.out.println(i);
}
}
So your first mistake is that you are putting everything inside your main method.
For this project I have to create a rational number class that has 2 parts an int numerator and int denominator. I had to add two contractions where the negative denominator has to be moved to the numerator. I also added getters and setters and a toString(). The data should print as numerator/denominator.
I also had to code member methods for addition, subtraction, multiplications, and division and negate(?) I am not sure what that last part means.
I have the class done already but Eclipse is giving me an error with the add and subtract method around the part where I typed "temp". Please let me know if I have anything that is incorrect or if I am missing something.
public class Rational {
private int numerator;
private int denominator;
public Rational()
{
numerator = 0;
denominator = 1;
}
public Rational(int n, int d, int num, int denom)
{
if (d < 0)
{
num = -n;
denom = d;
}
else if (d == 0)
{
num = n;
denom = 1;
}
else
{
num = n;
denom = 0;
}
}
public int getNumerator()
{
return numerator;
}
public int getDenominator()
{
return denominator;
}
public void setNumerator(int n)
{
numerator = n;
}
public void setDenominator(int n, int d, int num, int denom)
{
denominator = d;
if (d < 0)
{
num = -n;
denom = d;
}
else if (d == 0)
{
num = n;
denom = 1;
}
else
{
num = n;
denom = 0;
}
}
public String toString()
{
return numerator + "/" + denominator;
}
public boolean equals (Rational other)
{
if(numerator * other.denominator == denominator * other.numerator)
return true;
else
return false;
}
public boolean notequals(Rational other)
{
if (numerator * other.denominator != denominator * other.numerator)
return true;
else
return false;
}
//subtract method
public Rational subtract(Rational other)
{
Rational temp;
temp.numerator = numerator * other.denominator - denominator * other.numerator;
temp.denominator = denominator * other.denominator;
return temp;
}
//add method
public Rational add(Rational other)
{
Rational temp;
temp.numerator = numerator * other.denominator + denominator * other.numerator;
temp.denominator = denominator * other.denominator;
return temp;
}
public boolean lessThan(Rational other)
{
return(numerator * other.denominator < denominator * other.numerator);
}
public boolean greterThan(Rational other)
{
return(numerator * other.denominator > denominator * other.numerator);
}
public boolean lessThanEqualTo(Rational other)
{
return(numerator * other.denominator <= denominator * other.numerator);
}
public boolean greaterThanEqual(Rational other)
{
return(numerator * other.denominator >= denominator * other.numerator);
}
}
I am however struggling with the main to test each method.
Here is what I have so far:
public class Project4 {
public static void main(String[] args) {
Rational a = new Rational();
Rational b = new Rational();
Rational c;
c = a.add(b);
}
}
//Here goes commented code:
public class Rational
{
private int numerator; // You can declare private variables here all right
private int denominator;
// This constructor creates a new object of the class Rational. Objects are instances of that class, all right?
public Rational()
{
numerator = 0;
denominator = 1;
//private int numerator = 0;
//private int denominator = 1; // I get it, you need them even when not giving arguments, but it is better to do stuff in constructors. You better try to make declarations in the constructor and not in the begining of a class, if possible.
}
// Here is the constructor overriden, so you can create an instance that contains 4 arguments. (n,d,num,denom) Good.
public Rational(int n, int d, int num, int denom)
{
// You repeat yourself in the constructor.
// public void setDenominator(int n, int d, int num, int denom) does the same thing right?
// I don't remember now, but I think that on instantiation you can't use methods, if you don't add the word static.
// public static void setDenominator(int n, int d, int num, int denom) will make you able to call it in the constructor!
if (d < 0)
{
num = -n;
denom = d;
}
else if (d == 0)
{
num = n;
denom = 1;
}
else
{
num = n;
denom = 0;
}
}
public int getNumerator()
{
return numerator;
}
public int getDenominator()
{
return denominator;
}
public void setNumerator(int n)
{
numerator = n;
}
public void setDenominator(int n, int d, int num, int denom) // FIX IT. ADD STATIC
{
denominator = d;
if (d < 0)
{
num = -n;
denom = d;
}
else if (d == 0)
{
num = n;
denom = 1;
}
else
{
num = n;
denom = 0;
}
}
public String toString()
{
return numerator + "/" + denominator;
}
public boolean equals (Rational other)
{
if(numerator * other.denominator == denominator * other.numerator)
return true;
else
return false;
}
public boolean notequals(Rational other)
{
if (numerator * other.denominator != denominator * other.numerator)
return true;
else
return false;
}
//subtract method
public Rational subtract(Rational other)
{
Rational temp;
temp.numerator = numerator * other.denominator - denominator * other.numerator;
temp.denominator = denominator * other.denominator;
return temp;
} // THIS RETURNS temp THAT IS AN OBJECT OF THE TYPE Rational!!! Remember that.
//add method
public Rational add(Rational other)
{
Rational temp;
temp.numerator = numerator * other.denominator + denominator * other.numerator;
temp.denominator = denominator * other.denominator;
return temp;
}// THIS RETURNS temp THAT IS AN OBJECT OF THE TYPE Rational!!! Remember that.
public boolean lessThan(Rational other)
{
return(numerator * other.denominator < denominator * other.numerator);
}// What type is this method return? Here is the gap you must fill. If you learn how to handel what methods return, you will be fine. Try stuff out.
public boolean greterThan(Rational other)
{
return(numerator * other.denominator > denominator * other.numerator);
}
public boolean lessThanEqualTo(Rational other)
{
return(numerator * other.denominator <= denominator * other.numerator);
}
public boolean greaterThanEqual(Rational other)
{
return(numerator * other.denominator >= denominator * other.numerator);
}
}
So I have a List<Number> that contains both Doubles and Integers, I have to loop through the List and randomize each Number by +- 25%
This is an example similar to my code:
public class ListTester {
public static void main(String[] args){
ListTester lt = new ListTester();
}
public ListTester(){
int a = 1;
int b = 2;
double d = 3.5;
randomizableStats = new ArrayList(Arrays.asList(a, b, d));
randomizeStats();
}
protected List <Number> randomizableStats;
protected void randomizeStats(){
List<Number> randomizedStats = new ArrayList<>();
Random r = new Random();
for (Number n : randomizableStats){
int l = r.nextInt(1);
int i = r.nextInt(25);
if (l == 1){
if (n instanceof Integer) {
Integer n2 = (Integer) n;
n2 = n2 + (i / 100 * n2) + 1;
randomizedStats.add(n2);
} else if (n instanceof Double) {
Double n2 = (Double) n;
double d = (double) i;
n2 = n2 + (d / 100 * n2);
randomizedStats.add(n2);
}
} else {
if (n instanceof Integer) {
Integer n2 = (Integer) n;
n2 = n2 - (i / 100 * n2) - 1;
randomizedStats.add(n2);
} else if (n instanceof Double) {
Double n2 = (Double) n;
double d = (double) i;
n2 = n2 - (d / 100 * n2);
randomizedStats.add(n2);
}
}
}
for (Number n : randomizableStats){
System.out.print(n);
}
for (Number n : randomizedStats){
System.out.print(n);
}
}
}
The question is, is there a better way to write this, without having to go through a forced casting to Integer\Double complicating everything with additional if statements?
If you don't mind converting everything to double, you can use Number.doubleValue().
for (Number n : randomizables) {
int i = r.nextInt(1);
int l = r.nextInt(24) + 1;
if (i == 1) {
double d = n.doubleValue();
d = d + (d * l/100);
// do something with d
}
}
Well, as a design exercise one solution to avoid using instaceof, which in general is discourage (I'll comment on that latter), one solution is to use polymorphism. In your case for instance, you can create the following classes:
public abstract class NewNumber {
protected Number number;
public abstract NewNumber multiply(int m);
public Number toNumber() {
return this.number;
}
}
public class NewNumberInt extends NewNumber{
public NewNumberInt(Integer number) {
this.number = number;
}
#Override
public NewNumber multiply(int m) {
int out = this.number.intValue()*m;
return new NewNumberInt(out);
}
}
public class NewNumberDou extends NewNumber{
public NewNumberDou(Double number) {
this.number = number;
}
#Override
public NewNumber multiply(int m) {
double out = this.number.doubleValue()*m;
return new NewNumberDou(out);
}
}
With this, your program can be rewritten in the following way
int a = 1;
int b = 2;
double d = 3.5;
List<NewNumber> randomizables = new ArrayList<NewNumber>();
randomizables.add(new NewNumberInt(a));
randomizables.add(new NewNumberInt(b));
randomizables.add(new NewNumberDou(d));
// Example on how to convert from NewNumber to Number
List<Number> randomizablesNumber = new ArrayList<Number>();
for (NewNumber numNew:randomizables) randomizablesNumber.add(numNew.toNumber());
public void randomize(){
Random r = new Random();
for (NewNumber n : randomizables){
int i = r.nextInt(1);
int l = r.nextInt(24)+1;
if (i == 1){
NewNumber n2 = n.multiply(l/100);
}
}
}
The question is whether it is worth it to write all this just to avoid the usage of instanceof. From a design point of view of course it is and I personally prefer to spend 2 more minutes but have something well done, than just save these minutes and have something that is not nice. However, I understand that sometimes simple is best...
I have two methods: power and factorial:
public static long pow(int x, int n) {
long p = x;
for (int i = 1; i < n; i++) {
p *= x;
}
return p;
}
public static long fact(int n) {
long s = n;
for (int i = 1; i < n; i++ ) {
s *= i;
}
return s;
}
that are returning longs. When I want to use them in new method evaluating Exponential function i get wrong results comparing to Math.exp(x). My code:
public static void exp(int x, double eps) {
int i = 1;
double pow = 1.0;
double fact = 1.0;
double sum = 0.0;
double temp;
do {
temp = pow/fact;
sum += temp;
pow = pow(x, i);
fact = fact(i);
i++;
}
while (temp > eps);
System.out.println("Check: " + Math.exp(x));
System.out.println("My: " + sum);
}
public static void main() {
int x = 10;
double eps = 0.0000000000001;
exp(x, eps);
}
and the output for x=10 is:
Check: 22026.465794806718
My: 21798.734894914145
the larger x, the bigger "loss of precision" (not exactly, because you can't really call it precise...).
The twist is, when methods power and factorial return double then the output is correct. Can anyone explain me how to make it work?
Methods pow and fact must return long and I must use them in exp (college assignment).
If you try this pow method:
public static long pow(int x, int n) {
long p = x;
System.out.println("Pow: "+x+","+n);
for (int i = 1; i < n; i++) {
p *= x;
System.out.println(p);
}
return p;
}
You get this output:
...
Pow: 10,20
100
1000
10000
...
...
1000000000000000
10000000000000000
100000000000000000
1000000000000000000
-8446744073709551616
7766279631452241920
The long value overflows: 10^20 is just too big to fit in a long.
Methods pow and fact must return long and I must use them in exp (college assignment).
Then there is not much you can do to fix it. You could throw an exception if eps is too small.
How large is x typically? It could be integer overflow. Try changing all the int arguments in pow and fact to be long instead.
Long data types can't handle decimal precision that's why you're values are wrong with long. Why don't you just have the functions return the double values?
Edit: Heres what I came up with:
public static long pow(int x, int n)
{
double p = x;
for (int i = 1; i < n; i++) {
p *= x;
}
return (long)p;
}
public static long fact(int n)
{
double s = n;
for (int i = 1; i < n; i++ ) {
s *= i;
}
return (long)s;
}
public static void exp(int x, double eps)
{
double pow = 1.0;
double fact = 1.0;
double sum = 0.0;
double temp;
for(int ii=1; ii < 100; ii++)
{
pow = pow(x, ii);
fact = fact(ii);
temp = (double)pow/(double)fact;
temp = temp == 1 ? 0 : temp;
sum += temp;
}
System.out.println("Check: " + Math.exp(x));
System.out.println("My: " + sum);
}
public static void main(final String[] args)
{
int x = 10;
double eps = 0.0000000000001;
exp(x, eps);
}
That's about the closest you're going to get without using the decimals.
Check: 22026.465794806718
My: 21946.785573087538