Converting double to fraction using BigInteger [duplicate] - java

This question already has answers here:
How do I print my Java object without getting "SomeType#2f92e0f4"?
(13 answers)
Closed 7 years ago.
I'm learner of Java.
I'm trying to convert decimal to fraction using BigInteger in Rational class.
If I print the numerator and denominator, right output comes out.
However, when I add, subtract, multiply, and divide, some strange output come out.
For example when I inputs
3.25 -3
The output is
13 4
-3 1
RationalTest#14ae5a5
RationalTest#7f31245a
RationalTest#6d6f6e28
RationalTest#135fbaa4
What is wrong with my code? What is that hashcode?
I couldn't find out in the internet, so I need your help:<
import java.util.Scanner;
import java.math.*;
public class TestTest
{
public static void main(String[] args)
{
Scanner sc = new Scanner(System.in);
RationalTest r1 = RationalTest.getFraction(sc.next());
RationalTest r2 = RationalTest.getFraction(sc.next());
//Test if the right numerator and denominator comes out
System.out.println(r1.getNumerator()+" "+r1.getDenominator());
System.out.println(r2.getNumerator()+" "+r2.getDenominator());
System.out.println(r1.add(r2));
System.out.println(r1.subtract(r2));
System.out.println(r1.multiply(r2));
System.out.println(r1.divide(r2));
}
}
class RationalTest extends Number implements Comparable<RationalTest>
{
private static final long serialVersionUID = 1L;
private BigInteger numerator = BigInteger.ZERO;
private BigInteger denominator = BigInteger.ONE;
public RationalTest()
{
this(BigInteger.ZERO, BigInteger.ONE);
}
//Find GCD of numerator and denominator
public RationalTest(BigInteger numerator, BigInteger denominator)
{
BigInteger gcd = gcd(numerator, denominator);
this.numerator = ((denominator.compareTo(BigInteger.ZERO)>0) ? new BigInteger("1"):new BigInteger("-1")).multiply(numerator.divide(gcd));
this.denominator = denominator.abs().divide(gcd);
}
//Converting decimal to fraction
public static RationalTest getFraction(String s)
{
int result=-1;
for(int i=0; i<s.length(); i++)
{
if(s.charAt(i)=='.')
{
result=1;
break;
}
else
result=0;
}
//If result=1, String s is a decimal
if(result==1)
{
double d = Double.parseDouble(s);
long num = (long) Math.floor(d); // Only the int part
double denom = d-num; // Only the decimal part
int digitDec = s.length()-1-s.indexOf('.');
long up = (int) (denom*Math.pow(10, digitDec)); // numerator of denom
long down = (int) Math.pow(10, digitDec); // denominator of denim
return new RationalTest(BigInteger.valueOf(down*num+up), BigInteger.valueOf(down));
}
//If result=0, String s is not a decimal
else
{
return new RationalTest(BigInteger.valueOf(Long.parseLong(s)), BigInteger.ONE);
}
}
private static BigInteger gcd(BigInteger n, BigInteger d)
{
BigInteger n1 = n.abs();
BigInteger n2 = d.abs();
BigInteger gcd = BigInteger.ONE;
for(BigInteger k=BigInteger.ONE; k.compareTo(n1)<=0 && k.compareTo(n2)<=0; k=k.add(BigInteger.ONE))
{
if(n1.mod(k).equals(BigInteger.ZERO) && n2.mod(k).equals(BigInteger.ZERO))
gcd = k;
}
return gcd;
}
public BigInteger getNumerator()
{
return numerator;
}
public BigInteger getDenominator()
{
return denominator;
}
public RationalTest add(RationalTest secondRationalTest)
{
BigInteger n = (numerator.multiply(secondRationalTest.getDenominator())).add(denominator.multiply(secondRationalTest.getNumerator()));
BigInteger d = denominator.multiply(secondRationalTest.getDenominator());
return new RationalTest(n, d);
}
public RationalTest subtract(RationalTest secondRationalTest)
{
BigInteger n = (numerator.multiply(secondRationalTest.getDenominator())).subtract(denominator.multiply(secondRationalTest.getNumerator()));
BigInteger d = denominator.multiply(secondRationalTest.getDenominator());
return new RationalTest(n, d);
}
public RationalTest multiply(RationalTest secondRationalTest)
{
BigInteger n = numerator.multiply(secondRationalTest.getNumerator());
BigInteger d = denominator.multiply(secondRationalTest.getDenominator());
return new RationalTest(n, d);
}
public RationalTest divide(RationalTest secondRationalTest)
{
BigInteger n = numerator.multiply(secondRationalTest.getDenominator());
BigInteger d = denominator.multiply(secondRationalTest.getNumerator());
return new RationalTest(n, d);
}
#Override
public boolean equals(Object other)
{
if((this.subtract((RationalTest)(other))).getNumerator().equals(BigInteger.ZERO))
return true;
else
return false;
}
#Override
public int intValue()
{
return (int)doubleValue();
}
#Override
public float floatValue()
{
return (float)doubleValue();
}
#Override
public double doubleValue()
{
double x = this.getNumerator().doubleValue();
double y = this.getDenominator().doubleValue();
return x/y;
}
#Override
public long longValue()
{
return (long)doubleValue();
}
#Override
public int compareTo(RationalTest o) {
if(this.subtract(o).getNumerator().compareTo(BigInteger.ZERO)>0)
return 1;
else if(this.subtract(o).getNumerator().compareTo(BigInteger.ZERO)<0)
return -1;
else
return 0;
}
}

Oh I found out that I have to return string using toString()..
Thanks for your help!

Related

How to fix this 1/0 (infinity)?

The purpose of my code is to write a program that computes the following summation series using the Rational class: 1/2 + 2/3 + 3/4 + ... + 99/100.
My code is shown as follows:
import java.math.BigInteger;
public class Exercise {
public static void main(String[] args){
final BigInteger N = new BigInteger("99");
RationalV8 sum = new RationalV8();
for (BigInteger i = BigInteger.ONE; i.compareTo(N) <= 0; i = i.add(BigInteger.ONE)){
sum = sum.add(new RationalV8(i, i.add(BigInteger.ONE)));
}
System.out.println("The sum : " + sum + " = "
+ sum.doubleValue());
}
}
class RationalV8 extends Number implements Comparable <RationalV8>{
private BigInteger numerator = BigInteger.ZERO;
private BigInteger denominator = BigInteger.ONE;
public RationalV8(){
this(BigInteger.ZERO, BigInteger.ONE);
}
public RationalV8( BigInteger numerator, BigInteger denominator){
BigInteger gcd = gcd(numerator, denominator);
if (denominator.compareTo(BigInteger.ZERO) < 0 ){
this.numerator = numerator.multiply(new BigInteger("-1")).divide(gcd);
} else {
this.numerator = numerator.divide(gcd);
}
this.denominator = denominator.abs().divide(gcd);
}
public static BigInteger gcd(BigInteger n, BigInteger d){
BigInteger n1 = n.abs();
BigInteger n2 = d.abs();
BigInteger gcd = BigInteger.ONE;
for (BigInteger i = BigInteger.ONE; i.compareTo(n1) <= 0 && i.compareTo(n2) <= 0;
i = i.add(BigInteger.ONE) ){
if (n1.remainder(i).equals(BigInteger.ZERO) && n2.remainder(i).equals(BigInteger.ZERO)){
gcd = i;
}
}
return gcd;
}
public BigInteger getNumerator(){
return numerator;
}
public BigInteger getDenominator(){
return denominator;
}
public RationalV8 add(RationalV8 secondRational){
BigInteger n = numerator.multiply(secondRational.getDenominator()).add(
denominator.multiply(secondRational.getNumerator()));
BigInteger d = denominator.multiply(secondRational.getDenominator());
return new RationalV8(n, d);
}
public RationalV8 subtract(RationalV8 secondRational){
BigInteger n = numerator.multiply(secondRational.getDenominator()).subtract(
denominator.multiply(secondRational.getNumerator()));
BigInteger d = denominator.multiply(secondRational.getDenominator());
return new RationalV8(n, d);
}
public RationalV8 multiply(RationalV8 secondRational){
BigInteger n = numerator.multiply(secondRational.getNumerator());
BigInteger d = denominator.multiply(secondRational.getDenominator());
return new RationalV8(n, d);
}
public RationalV8 divide(RationalV8 secondRational){
BigInteger n = numerator.multiply(secondRational.getDenominator());
BigInteger d = denominator.multiply(secondRational.getNumerator());
return new RationalV8(n, d);
}
#Override
public int compareTo(RationalV8 o){
if ( (this.subtract((RationalV8) o)).getNumerator().compareTo(BigInteger.ZERO) > 0){
return 1;
}
else if ( (this.subtract((RationalV8) o)).getNumerator().compareTo(BigInteger.ZERO) < 0){
return -1;
} else {
return 0;
}
}
#Override
public String toString(){
if (denominator.equals(BigInteger.ONE)){
return numerator + " ";
} else {
return numerator + "/" + denominator;
}
}
#Override
public boolean equals(Object param1){
if ((this.subtract( (RationalV8) (param1) )).getNumerator().equals(BigInteger.ZERO) ){
return true;
} else {
return false;
}
}
#Override
public int hashCode(){
return new Double( this.doubleValue() ).hashCode();
}
//#Override
public int intValue(){
return (int)doubleValue();
}
//#Override
public float floatValue(){
return (float)doubleValue();
}
public double doubleValue(){
return numerator.doubleValue() / denominator.doubleValue();
}
public long longValue(){
return (long)doubleValue();
}
}
The running output for this code is:
The sum of the first series is 1/0 = Infinity.
But the output is incorrect because of integer overflow.
Can anyone tell me where is the problem?
I think the line BigInteger n2 = n.abs(); should have been BigInteger n2 = d.abs();. I am not sure this is the only bug.

Fraction calculator adding

Hi I'm new to java and am working on a Fraction calculator and I am unable to figure out how to get the calculator to reduce simple fractions and add mixed fractions.
Example:
Reduction: 1/2 + -5/6 = -1/3
Mixed Fractions: 4_15/16 + -3_11/16 = 1_1/4
Edit: For mixed fractions, I tried to subtract the numerator from the denominator for num>den to get the whole and the remainder and return it and print but it's not printing out anything.
import java.util.Scanner;
public class Fraction {
public static void main(String[] args) {
System.out.println("Enter an Expression or quit:");
Scanner input = new Scanner(System.in);
String text = input.nextLine();
while (!text.equals("quit")){
String frac1 = text.substring(0,text.indexOf(" "));
String oper = text.substring((text.indexOf(" "))+1,(text.indexOf(" "))+2);
String frac2 = text.substring((text.indexOf(" "))+3);
int fn1 = num(frac1); //frac1 numerator
int fd1 = den(frac1); //frac1 denominator
int fn2 = num(frac2); //frac2 numerator
int fd2 = den(frac2); //frac2 denominator
if (oper.equals("+")){
int sumfinalnum = add(fn1, fd1, fn2, fd2);
if (fd1 == 1 && fd2 == 1){
System.out.println(sumfinalnum);
}
else if ((fn1 + fn2)==0){
System.out.println("0");
}
else if (fd1 == fd2){
if (sumfinalnum>fd1){
System.out.println(extractWholePart(sumfinalnum,fd1)+"_"+extractNumPart(sumfinalnum,fd1)+"/"+fd1);
}
else{
System.out.println(sumfinalnum+"/"+fd1);
}
}
else if (!(fd1 == fd2)){
System.out.println(sumfinalnum+"/"+(fd1*fd2));
}
System.out.println("Enter an Expression or quit:");
text = input.nextLine();
}
}
}
public static int num(String input){
if (input.contains("_")){ //mixed to improper
String a = input.substring(0,input.indexOf("_"));
String b = input.substring((input.indexOf("_"))+1,input.indexOf("/"));
String c = input.substring((input.indexOf("/"))+1);
int a1 = Integer.parseInt(a);
int b1 = Integer.parseInt(b);
int c1 = Integer.parseInt(c);
int d = a1*c1;
int e = d+b1;
return e;
}
else if (!input.contains("/")){
int input1 = Integer.parseInt(input);
return input1;
}
else {
String strnum1 = input.substring(0,input.indexOf("/"));
int num1 = Integer.parseInt(strnum1);
return num1;
}
}
public static int den(String input){
if(!input.contains("/")) { //whole
return 1;
}
String strnum2 = input.substring((input.indexOf("/"))+1);
int num2 = Integer.parseInt(strnum2);
return num2;
}
public static int add(int fn1,int fd1,int fn2,int fd2){
if (fd1 == fd2){ //matching denominator
int numadd = fn1 + fn2;
return numadd;
}
else if (fd1 == 1 && fd2 == 1){ //whole numbers no denom
int sum = fn1 + fn2;
return sum;
}
else if (!(fd1 == fd2)){ //different denominator***
int dencomadd = fd1*fd2;
int gcd1 = dencomadd/fd1;
int gcd2 = dencomadd/fd2;
int comf1num = fn1*gcd1;
int comf2num = fn2*gcd2;
int total = comf1num+comf2num;
return total;
}
else{
return 0;
}
}
public static int extractWholePart(int finalnum, int finalden){
int whole = 0;
while (finalnum > finalden){
whole++;
}
return whole;
}
public static int extractNumPart(int finalnum, int finalden){
while (finalnum > finalden){
finalnum -= finalden;
}
return finalnum;
}
}
Let's start with - It's java, don't be afraid to use bigger variable names. fn1 could very well be called fraction1Numerator.
Next, have a single method to do what it's designed to do. Having an add method that needs four else-ifs in main is not a really good idea.
Creating an object Fraction that would have member variables numerator and denominator would allow your add function to return the entire answer. After all you have the code to add mixed fractions that looks good.
class Fraction{
public int whole;
public int numerator;
public int denominator;
}
I also added "whole" to indicate whole part after simplification. add function would than have signature
public static Fraction add(Fraction fraction1, Fraction fraction2) ...
Extracting whole numbers is simple - subtract denominator from numerator until you can't do that anymore.
public void extractWholePart(Fraction fraction){
int whole = 0;
while (fraction.numerator > fraction.denominator){
whole++;
fraction.numerator -= fraction.denominator;
}
fraction.whole = whole;
}
simplification on the other hand is just dividing both nominator and denominator by the greatest common divisor - algorythm for calculating that is easily findable on the internet.
Try something like this
float mixedToDecimal(String data)
// data would be like this "1 5/8";
String[] parts = data.split(" ");
if(!(parts.lenght > 0)) // this mean that if data is NOT mixedfraction then just return -1
return -1;
float value = Integer.parseInt(parts[0]);
if (parts.length > 1) {
// has fractional part
parts = parts[1].split("/");
float numerator = Integer.parseInt(parts[0]);
float denominator = Integer.parseInt(parts[1]);
value += numerator / denominator;
}
// value contains 1.625
return value;

Fraction.java Keep getting object address not the values I want

I am working on this program and keep getting this result.
To convert fractional measures,
enter the fractional measure you want to convert: 3/4
Enter the fractional amount to reduce/increase it by: 1/2
The converted measurement is: Fraction#6750cf54
The part is bold is the problem.
This is my main program.
import java.util.*; // Scanner
import java.io.*; // PrintStream
public class Pierre1 extends Object
{
public static void main(String args[])
{
PrintStream theScreen = new PrintStream(System.out);
Scanner theKeyboard = new Scanner(System.in);
theScreen.println("\nTo convert fractional measures,");
theScreen.print(" enter the fractional measure you want to convert: ");
Fraction oldMeasure = new Fraction();
oldMeasure.read(theKeyboard);
theScreen.print("\nEnter the fractional amount to reduce/increase it by: ");
Fraction scaleFactor = new Fraction(1,6);
scaleFactor.read(theKeyboard);
Fraction newMeasure = oldMeasure.times(scaleFactor);
theScreen.print("\nThe converted measurement is: ");
theScreen.print(newMeasure);
theScreen.println();
theScreen.println();
}
}
This is my other program.
import java.util.*; // Scanner
import java.io.*; // PrintStream
public class Fraction extends Object
{
private int myNumerator = 0;
private int myDenominator = 0;
public void print(PrintStream out)
{
System.out.print(myNumerator + "/" + myDenominator);
}
public Fraction()
{
myNumerator = 0;
myDenominator = 1;
}
public Fraction(int numerator, int denominator)
{
myNumerator = numerator;
myDenominator = denominator;
}
private int numerator()
{
return myNumerator;
}
private int denominator()
{
return myDenominator;
}
public void read (Scanner in)
{
String fraction = in.next();
StringTokenizer parser = new StringTokenizer(fraction, "/", false);
if (parser.countTokens() != 2)
throw new RuntimeException("Bad Fraction Format");
myNumerator = Integer.parseInt(parser.nextToken());
myDenominator = Integer.parseInt(parser.nextToken());
}
Fraction times(Fraction rightOperand)
{
Fraction result
= new Fraction(myNumerator*rightOperand.numerator(),
myDenominator*rightOperand.denominator());
result.simplify(result);
return result;
}
public Fraction simplify(Fraction getGcd)
{
Fraction result = new Fraction();
int num = numerator();
int den = denominator();
int gcd = greatestCommonDivisor(num, den);
if (gcd == 0)
return result;
else
{
myNumerator = myNumerator / gcd;
myDenominator = myDenominator / gcd;
}
return result;
}
private static int greatestCommonDivisor(int alpha, int beta)
{
alpha = Math.abs(alpha); // take absolute values of operands
beta = Math.abs(beta);
if (beta == 0) // base case
return alpha;
else // induction step
{
int remainder = alpha % beta;
return greatestCommonDivisor(beta, remainder);
}
}
}
What do I need to do to fix this?
I have been scanning the programs to find the problem, but my limited java experience is getting the best of me. Any help is greatly appreciated. Thanks in advance!
have a look at the Fraction class that I use (it fixes some of your flaws: numerator and denumerator should be final, etc.)
// code by jph
package sys.mat;
/** non degenerate integer fraction in normal form */
public class Fraction implements Comparable<Fraction> {
/** numerator */
public final int num;
/** denominator (always greater than zero) */
public final int den;
public static int gcd(int a, int b) {
if (b == 0)
return a;
return gcd(b, a % b);
}
/** #param num
* #param den has to be non-zero
* #throws {#link ArithmeticException} if den is zero */
public Fraction(final int num, final int den) {
int gcd = gcd(num, den);
int res = den / gcd;
if (0 < res) {
this.num = num / gcd;
this.den = res;
} else {
this.num = -num / gcd;
this.den = -res;
}
}
public Fraction add(Fraction myFraction) {
return new Fraction(num * myFraction.den + den * myFraction.num, den * myFraction.den);
}
public Fraction sub(Fraction myFraction) {
return new Fraction(num * myFraction.den - den * myFraction.num, den * myFraction.den);
}
public Fraction mul(Fraction myFraction) {
return new Fraction(num * myFraction.num, den * myFraction.den);
}
public Fraction mul(int myInt) {
return new Fraction(num * myInt, den);
}
public Fraction div(Fraction myFraction) {
return new Fraction(num * myFraction.den, den * myFraction.num);
}
/** also denoted reciprocal
*
* #return den/num */
public Fraction inverse() {
return new Fraction(den, num);
}
/** #return true if den == 1 */
public boolean isInteger() {
return den == 1;
}
public double toDouble() {
return num / (double) den;
}
/** may only be called if isInteger() returns true
*
* #return num */
public int toInteger() {
if (!isInteger()) // assert den == 1
throw new RuntimeException(toString() + " is no integer");
return num;
}
#Override
public int compareTo(Fraction myFraction) {
// return num * myFraction.den - den * myFraction.num; // does not work for big integers
return Double.compare(toDouble(), myFraction.toDouble());
}
public boolean equalsInteger(int value) {
return equals(new Fraction(value, 1));
}
#Override
public boolean equals(Object myObject) {
if (myObject == null) // || !(myObject instanceof Fraction)
return false;
Fraction myFraction = (Fraction) myObject;
return num == myFraction.num && den == myFraction.den; // sufficient since in normal form
}
#Override
public int hashCode() {
// n / 1 is mapped to n, thus is identical to getInteger()
return num + den - 1;
}
#Override
public String toString() {
return num + "/" + den;
}
}

Why aren't the values of these variables being set properly by the methods getFraction1 and getFraction2?

I have tried to write TestFraction in such a way that the main method calls on the methods getFraction1 and getFraction2 to create two Fractions: fr1 (a/b) and fr2 (a/b). getFraction1 and getFraction2 prompt the user for two integers, a and b, and call on getNumber to capture these integers. Fraction then performs calculations on fr1 and fr2. The problem is, when I run TestFraction, the values of a and b are left at 1, which is what they're set to in Fraction. Can anyone give me a hint as to why getFraction1 and getFraction2 aren't actually passing the values of a and b into fr1 and fr2?
Here is my code for TestFraction:
package Fraction;
import java.io.*;
import java.util.*;
public class TestFraction
{
static Scanner console = new Scanner (System.in);
private static int getNumber() throws InputMismatchException
{
return console.nextInt();
}
private static Fraction getFraction1()
{
int a=1, b=1;
Fraction frac = new Fraction ();
while (true) {
// prompt to enter a numerator and a denominator
System.out.println("Input 1st fraction numerator and denominator");
// input the numerator and the denominator using getNumber()
try {
a = getNumber();
b = getNumber();
}
catch (Exception e)
{
System.out.println("Exception: "+e.toString());
console.nextLine();
continue;
}
return frac;
// return new Fraction if OK
// otherwise print an error message
}
}
private static Fraction getFraction2()
{
int a=1, b=1;
Fraction frac = new Fraction ();
while (true) {
// prompt to enter a numerator and a denominator
System.out.println("Input 2nd fraction numerator and denominator");
// input the numerator and the denominator using getNumber()
try {
a = getNumber();
b = getNumber();
}
catch (Exception e)
{
System.out.println("Exception: "+e.toString());
console.nextLine();
continue;
}
return frac;
// return new Fraction if OK
// otherwise print an error message
}
}
public static void main(String[] args)
{
Fraction fr1 = new Fraction ();
fr1 = getFraction1();
Fraction fr2 = new Fraction ();
fr2 = getFraction2();
Fraction res = new Fraction();
// define other variables including res and fr2
res = Fraction.add (fr1, fr2);
System.out.println(fr1+" + "+fr2+" = "+res);
res = Fraction.subtract (fr1, fr2);
System.out.println(fr1+" - "+fr2+" = "+res);
res = Fraction.multiply (fr1, fr2);
System.out.println(fr1+" * "+fr2+" = "+res);
res = Fraction.divide (fr1, fr2);
System.out.println(fr1+" / "+fr2+" = "+res);
res = Fraction.lessThan (fr1, fr2);
System.out.println(fr1+" "+res+" "+fr2);
// test subtract, multiply, divide, lessThan methods
// each test has to print a description, a result,
// and, possibly, a error message if the calculation fails
}
}
And here is Fraction:
package Fraction;
public class Fraction
{
protected int a;
protected int b;
public Fraction()
{
a = 1;
b = 1;
}
public Fraction (int a, int b)
{
this.a=a;
this.b=b;
}
public int getNumerator()
{
return a;
}
public int getDenominator()
{
return b;
}
public void setNumerator(int a)
{
this.a=a;
}
public void setDenominator(int b)
{
this.b=b;
}
public String toString ()
{
return a+"/"+b;
}
public int gcd(int a, int b)
{
//ToDo implement Euclide algorithm
if (b==0) return a;
return gcd(b, a%b);
}
public void lowestTerms()
{
int g=gcd(a,b);
a=a/g;
b=b/g;
}
public static Fraction add(Fraction first, Fraction second)
{
Fraction result = new Fraction();
result.setNumerator(first.getNumerator()*second.getDenominator()
+ first.getDenominator()*second.getNumerator());
result.setDenominator(first.getDenominator()*second.getDenominator());
result.lowestTerms();
return result;
}
//ToDo methods subtract, multiply, divide, lessThan
public static Fraction subtract(Fraction first, Fraction second)
{
Fraction result = new Fraction();
result.setNumerator(first.getNumerator()*second.getDenominator()
- first.getDenominator()*second.getNumerator());
result.setDenominator(first.getDenominator()*second.getDenominator());
result.lowestTerms();
return result;
}
public static Fraction multiply(Fraction first, Fraction second)
{
Fraction result = new Fraction();
result.setNumerator(first.getNumerator()*second.getNumerator());
result.setDenominator(first.getDenominator()*second.getDenominator());
result.lowestTerms();
return result;
}
public static Fraction divide(Fraction first, Fraction second)
{
Fraction result = new Fraction();
result.setNumerator(first.getNumerator()*second.getDenominator());
result.setDenominator(first.getDenominator()*second.getNumerator());
result.lowestTerms();
return result;
}
public static Fraction lessThan(Fraction first, Fraction second)
{
if (first.getNumerator()*second.getDenominator() <=
first.getDenominator()*second.getNumerator()){
return first;
}
else {
return second;
}
}
}
You must use the Faction(int, int) constructor instead of Fraction() constructor:
Fraction frac = new Fraction ();
must be
Fraction frac = null;
//later in the code once you have a and b variables set and no exceptions...
frac = new Fraction (a, b);
OR use the setters:
frac.setNumerator(a);
frac.setDenominator(b);
before returning frac variable.
Looks like you are not setting the values you read from the console
a = getNumber();
b = getNumber();
frac.setNumerator(a);
frac.setDenominator(b);
by default a and b are set to 1, when you say
Fraction frac = new Fraction();
because the Fraction default constructor is defined like this
public Fraction()
{
a = 1;
b = 1;
}

Java: exception handling - something is wrong with my catch()

public class Fraction {
private int numerator; //
private int denominator; //
Fraction(int nume, int denom)
{
numerator = nume;
denominator = denom;
}
public Fraction divide(Fraction other ) throws FractionDivideByZeroException
{
int nume=0, denom=0;
try {
nume = (this.numerator * other.denominator);
denom = (this.denominator*other.numerator);
if(nume!=0 && denom==0) throw new FractionDivideByZeroException();
return new Fraction(nume, denom);
} catch (FractionDivideByZeroException e) {
e.printError();
}
return new Fraction(nume, denom);
}
}
class FractionDivideByZeroException extends Exception
{
void printError()
{
System.out.println("You can not divide by zero!");
}
}
this is the test class:
public class FractionTest {
public static void main(String[] args) {
// TODO Auto-generated method stub
Fraction frac1 = new Fraction(1,2);
Fraction frac2 = new Fraction(1,3);
Fraction frac3 = frac1.divide(frac2); // here's the error message saying "Unhandled exception type FractionDivideByZeroException"
System.out.println(frac3);
}
}
Take out throws declaration from your divide method. You are throwing it and then handling it there itself.
Your FractionTest uses frac1.divide and the compiler is asking you to handle the exception that is declared in the divide method.
You've said Divide throws FractionDivideByZeroException
public Fraction divide(Fraction other ) throws FractionDivideByZeroException
but written code to ensure it doesn't. The compiler doesn't know this so is complaining you/ve not handled the exception in the calling code
Look at your method signature:
public Fraction divide(Fraction other ) throws FractionDivideByZeroException
It says it throws the exception. The main method doesn't catch it, so the compiler will complain.
Catch it in the method or declare that you throw it, but not both.
I think your logic is flawed. You should never be able to create a Fraction with a zero denominator - your constructor should check that.
Your divide() method should be checking to ensure that the numerator of the divisor is not zero. That's the only way to get a divide by zero error.
When you construct the new Fraction that divide returns, the constructor should throw an exception.
Don't catch it in your divide() method; leave the throws clause and remove the try/catch. If it's a checked exception your test case has to catch it.
Here's how I'd write it:
package fraction;
public class Fraction implements Comparable
{
private int numerator;
private int denominator;
public Fraction()
{
this(0);
}
public Fraction(int numerator)
{
this(numerator,1);
}
Fraction(int numerator, int denominator)
{
if (denominator == 0)
throw new IllegalArgumentException("denominator cannot be zero");
this.numerator = numerator;
this.denominator = denominator;
if (this.numerator*this.denominator < 0)
{
this.numerator = -Math.abs(this.numerator);
this.denominator = Math.abs(this.denominator);
}
this.normalize();
}
public Fraction add(Fraction other)
{
return new Fraction(this.numerator*other.denominator+other.numerator*this.denominator, this.denominator*other.denominator);
}
public Fraction sub(Fraction other)
{
return new Fraction(this.numerator*other.denominator-other.numerator*this.denominator, this.denominator*other.denominator);
}
public Fraction mul(Fraction other)
{
return new Fraction(this.numerator*other.numerator, this.denominator*other.denominator);
}
public Fraction div(Fraction other)
{
return new Fraction(this.numerator*other.denominator, this.denominator*other.numerator);
}
#Override
public boolean equals(Object o)
{
if (this == o)
{
return true;
}
if (o == null || getClass() != o.getClass())
{
return false;
}
Fraction fraction = (Fraction) o;
if (denominator != fraction.denominator)
{
return false;
}
if (numerator != fraction.numerator)
{
return false;
}
return true;
}
#Override
public int hashCode()
{
int result = numerator;
result = 31 * result + denominator;
return result;
}
public int compareTo(Object o)
{
Fraction other = (Fraction) o;
int product1 = this.numerator*other.denominator;
int product2 = other.numerator*this.denominator;
return (product1-product2);
}
#Override
public String toString()
{
return numerator + "/" + denominator;
}
private void normalize()
{
int sign = 1;
if (this.numerator < 0)
{
sign = -1;
}
int gcd = greatestCommonDivisor(Math.abs(this.numerator), Math.abs(this.denominator));
this.numerator /= gcd;
this.denominator /= gcd;
this.numerator *= sign;
}
public static int greatestCommonDivisor(int m, int n)
{
int a = Math.max(m, n);
int b = Math.min(m, n);
if (a == 0)
return b;
if (b == 0)
return a;
while (a != b)
{
if (b > a)
b -= a;
else
a -= b;
}
return b;
}
}
And the partial unit test:
package fraction;
import org.junit.Assert;
import org.junit.Test;
public class FractionTest
{
#Test
public void testAdd()
{
Fraction x = new Fraction(3, 4);
Fraction y = new Fraction(5, 8);
Fraction expected = new Fraction(11, 8);
Assert.assertEquals(expected, x.add(y));
}
#Test
public void testSub()
{
Fraction x = new Fraction(3, 4);
Fraction y = new Fraction(5, 8);
Fraction expected = new Fraction(1, 8);
Assert.assertEquals(expected, x.sub(y));
}
#Test
public void testMul()
{
Fraction x = new Fraction(3, 4);
Fraction y = new Fraction(5, 8);
Fraction expected = new Fraction(15, 32);
Assert.assertEquals(expected, x.mul(y));
}
#Test
public void testDiv()
{
Fraction x = new Fraction(3, 4);
Fraction y = new Fraction(5, 8);
Fraction expected = new Fraction(6, 5);
Assert.assertEquals(expected, x.div(y));
}
#Test
public void testGreatestCommonDivisor()
{
Assert.assertEquals(Fraction.greatestCommonDivisor(48, 180), 12);
Assert.assertEquals(Fraction.greatestCommonDivisor(40902, 24140), 34);
Assert.assertEquals(Fraction.greatestCommonDivisor(2, 199), 1);
Assert.assertEquals(Fraction.greatestCommonDivisor(11, 8), 1);
Assert.assertEquals(Fraction.greatestCommonDivisor(1, 8), 1);
Assert.assertEquals(Fraction.greatestCommonDivisor(15, 32), 1);
Assert.assertEquals(Fraction.greatestCommonDivisor(6, 5), 1);
}
}
You stated that devide is a method that throws FractionDivideByZeroException.
your test function must catch it.
or... you function does not throw this exception so the throws FractionDivideByZeroException is redundant.
Add try/catch block to your main method. FractionDevidedByZeroException is a checked exception. You should surround them with try/catch. Otherwise you get this compilation error.
public static void main(String[] args) {
// TODO Auto-generated method stub
Fraction frac1 = new Fraction(1,2);
Fraction frac2 = new Fraction(1,3);
try {
Fraction frac3 = frac1.divide(frac2);
System.out.println(frac3);
} catch (FractionDevidedByZeroException e) {
e.printStackTrace();
}
}

Categories