Java 分数计数器 类
Java fraction counter with classes
由于某种原因,我在作业上遇到了困难。我有一个程序从输入文件中读取分数,将每一行分配给一个字符串,然后将内容保存到 class 分数(分子和分母)。然后将分数对象保存到名为 fractionList
.
的数组中
我有另一个 class FractionCounter
计算简化形式的分数的出现次数,如果有任何重复,那么程序将简单地添加到整数 "counter"那个对象。 FractionCounter
个对象存储在一个名为 fracCount
.
的对象列表中
我的问题是当我将一个对象添加到 FractionCounter
个对象的 fracCount
列表时。我正在使用一个分支语句来确定我是否应该添加一个新的分数元素(一个不匹配数组 fracCount
中其他分数的任何简化形式的元素)到 fracCount
,或者如果我应该在共享相同减少分数值的元素中向 counter
变量添加一个值。
一切正常,除非我试图确定派系对象是否为副本。使用我的代码,我的 fracCount
数组是空的。
这是我的代码
public class Fraction {
private int numerator;
private int denominator;
Fraction(){ // default, no arg constructor
}
// constructor that initializes data
Fraction(int numerator, int denominator){
this.numerator = numerator;
if(denominator > 1000){
this.denominator = 1;
}else if(numerator == denominator){
this.numerator = 1;
this.denominator = 1;
}else if(denominator == 0){
System.out.println("Zero is not a valid denominator");
}else{
this.denominator = denominator;
}
}
// compares this fraction object to 'other' fraction object
boolean equals(Fraction other){
if(this.numerator == other.numerator &&
this.denominator == other.denominator){
return true;
}else if((this.numerator / this.denominator) ==
(other.numerator / other.denominator)){
return true;
}else{
return false;
}
}
// gives user access to the numerator and denominator
public int getNumerator(){
return this.numerator;
}
public int getDenominator(){
return this.denominator;
}
}
public class FractionCounter extends Fraction{
private Fraction theFraction;
private int counter = 1;
FractionCounter(Fraction theFraction){
this.theFraction = theFraction;
}
public boolean compareAndIncrement(Fraction newFraction){
if((theFraction.getNumerator() / theFraction.getDenominator() ==
newFraction.getNumerator() / newFraction.getDenominator())){
this.counter++;
return true;
}else if(theFraction.getDenominator() == 0 ||
newFraction.getDenominator() == 0){
return false;
}else{
return false;
}
}
}
public class ObjectList {
private int N;
private Fraction[] fractionList;
private int numElements = 0;
public ObjectList(int n){
this.N = n;
this.fractionList = new Fraction[N];
}
public void add(Fraction next){
fractionList[numElements] = next;
numElements++;
}
public int size(){
return this.numElements;
}
public Fraction getFraction(int i){
return fractionList[i];
}
}
import java.util.Scanner;
import java.awt.List;
import java.io.*;
import java.util.Arrays;
public class FractionDriver {
public static void main(String[] args){
// creates scanner object
Scanner fractions = null;
// uses scanner to import fractions file and read how many lines
try{
fractions = new Scanner(new FileInputStream("fractions.txt"));
}catch(FileNotFoundException e){
System.out.println("Cannot find fractions.txt");
System.exit(0);
}
// creates a large array that stores the text file
String[] input = new String[100];
int numLines = 0; // counts the number of fractions
int numElement = 0; // counts the current index element
while(fractions.hasNextLine()){
input[numElement] = fractions.next();
numElement++;
numLines++;
}
fractions.close(); // closes the input stream
// create object list of fractions
ObjectList fractionList = new ObjectList(numLines);
ObjectList fractCount = new ObjectList(numLines);
int totalFractions = 0;
for(int i = 0; i < numLines; i++){
totalFractions++; // adds one on every new line
// creates an array for each fraction where frac[0] is the
// numerator and frac[1] is the denominator
String[] fract = input[i].split("/");
// converts the string values to integers
int numerator = Integer.parseInt(fract[0]);
int denom = Integer.parseInt(fract[1]);
// creates a fraction object and assigns instance variables
Fraction f = new Fraction(numerator, denom);
FractionCounter count = new FractionCounter(f);
// adds the fraction to the array if the denominator
// is not zero
if(f.getDenominator() != 0){
fractionList.add(f);
for(int j = 0; j < totalFractions; j++){
if(fractCount.getFraction(j) != null){
if(!f.equals(fractCount.getFraction(j))){
fractCount.add(count);
}else{
count.compareAndIncrement(f);
}
}
}
}
}
}
}
问题是你在除整数吗?
numerator/denominator
将 4/6 和 1/7 相除会发生什么?对于整数,它们都将产生 0,因此您会得到意想不到的相等性。
您可以转换为双倍
(double)numerator/(double)demoninator
但记住浮点比较是否相等并不明显,通常我们测试
if ( ( oneDouble - anotherDouble ) < someTinyValue )
我认为这是给您带来问题的行(在 Fraction
的 .equals
方法中:
(this.numerator / this.denominator) == (other.numerator / other.denominator)
它当前正在执行整数除法,因此 1/2 == 0 和 1/3 == 0,因此您的代码认为每个分数都已经在分数列表中。
您需要使用某种 epsilon 执行浮点运算。
Why Are Floating Point Numbers Inaccurate?
有一种非常自然的方法可以检查两个简单分数的值是否相等,而无需将它们转换为浮点数。
如果a/b = c/d
,则ad = bc
(b
或d
=0除外),所以:
boolean equals(Fraction other) {
if (this.denominator == 0 || other.denominator == 0)
return false; // undefined
return this.numerator * other.denominator == other.numerator * this.denominator;
}
由于某种原因,我在作业上遇到了困难。我有一个程序从输入文件中读取分数,将每一行分配给一个字符串,然后将内容保存到 class 分数(分子和分母)。然后将分数对象保存到名为 fractionList
.
我有另一个 class FractionCounter
计算简化形式的分数的出现次数,如果有任何重复,那么程序将简单地添加到整数 "counter"那个对象。 FractionCounter
个对象存储在一个名为 fracCount
.
我的问题是当我将一个对象添加到 FractionCounter
个对象的 fracCount
列表时。我正在使用一个分支语句来确定我是否应该添加一个新的分数元素(一个不匹配数组 fracCount
中其他分数的任何简化形式的元素)到 fracCount
,或者如果我应该在共享相同减少分数值的元素中向 counter
变量添加一个值。
一切正常,除非我试图确定派系对象是否为副本。使用我的代码,我的 fracCount
数组是空的。
这是我的代码
public class Fraction {
private int numerator;
private int denominator;
Fraction(){ // default, no arg constructor
}
// constructor that initializes data
Fraction(int numerator, int denominator){
this.numerator = numerator;
if(denominator > 1000){
this.denominator = 1;
}else if(numerator == denominator){
this.numerator = 1;
this.denominator = 1;
}else if(denominator == 0){
System.out.println("Zero is not a valid denominator");
}else{
this.denominator = denominator;
}
}
// compares this fraction object to 'other' fraction object
boolean equals(Fraction other){
if(this.numerator == other.numerator &&
this.denominator == other.denominator){
return true;
}else if((this.numerator / this.denominator) ==
(other.numerator / other.denominator)){
return true;
}else{
return false;
}
}
// gives user access to the numerator and denominator
public int getNumerator(){
return this.numerator;
}
public int getDenominator(){
return this.denominator;
}
}
public class FractionCounter extends Fraction{
private Fraction theFraction;
private int counter = 1;
FractionCounter(Fraction theFraction){
this.theFraction = theFraction;
}
public boolean compareAndIncrement(Fraction newFraction){
if((theFraction.getNumerator() / theFraction.getDenominator() ==
newFraction.getNumerator() / newFraction.getDenominator())){
this.counter++;
return true;
}else if(theFraction.getDenominator() == 0 ||
newFraction.getDenominator() == 0){
return false;
}else{
return false;
}
}
}
public class ObjectList {
private int N;
private Fraction[] fractionList;
private int numElements = 0;
public ObjectList(int n){
this.N = n;
this.fractionList = new Fraction[N];
}
public void add(Fraction next){
fractionList[numElements] = next;
numElements++;
}
public int size(){
return this.numElements;
}
public Fraction getFraction(int i){
return fractionList[i];
}
}
import java.util.Scanner;
import java.awt.List;
import java.io.*;
import java.util.Arrays;
public class FractionDriver {
public static void main(String[] args){
// creates scanner object
Scanner fractions = null;
// uses scanner to import fractions file and read how many lines
try{
fractions = new Scanner(new FileInputStream("fractions.txt"));
}catch(FileNotFoundException e){
System.out.println("Cannot find fractions.txt");
System.exit(0);
}
// creates a large array that stores the text file
String[] input = new String[100];
int numLines = 0; // counts the number of fractions
int numElement = 0; // counts the current index element
while(fractions.hasNextLine()){
input[numElement] = fractions.next();
numElement++;
numLines++;
}
fractions.close(); // closes the input stream
// create object list of fractions
ObjectList fractionList = new ObjectList(numLines);
ObjectList fractCount = new ObjectList(numLines);
int totalFractions = 0;
for(int i = 0; i < numLines; i++){
totalFractions++; // adds one on every new line
// creates an array for each fraction where frac[0] is the
// numerator and frac[1] is the denominator
String[] fract = input[i].split("/");
// converts the string values to integers
int numerator = Integer.parseInt(fract[0]);
int denom = Integer.parseInt(fract[1]);
// creates a fraction object and assigns instance variables
Fraction f = new Fraction(numerator, denom);
FractionCounter count = new FractionCounter(f);
// adds the fraction to the array if the denominator
// is not zero
if(f.getDenominator() != 0){
fractionList.add(f);
for(int j = 0; j < totalFractions; j++){
if(fractCount.getFraction(j) != null){
if(!f.equals(fractCount.getFraction(j))){
fractCount.add(count);
}else{
count.compareAndIncrement(f);
}
}
}
}
}
}
}
问题是你在除整数吗?
numerator/denominator
将 4/6 和 1/7 相除会发生什么?对于整数,它们都将产生 0,因此您会得到意想不到的相等性。
您可以转换为双倍
(double)numerator/(double)demoninator
但记住浮点比较是否相等并不明显,通常我们测试
if ( ( oneDouble - anotherDouble ) < someTinyValue )
我认为这是给您带来问题的行(在 Fraction
的 .equals
方法中:
(this.numerator / this.denominator) == (other.numerator / other.denominator)
它当前正在执行整数除法,因此 1/2 == 0 和 1/3 == 0,因此您的代码认为每个分数都已经在分数列表中。
您需要使用某种 epsilon 执行浮点运算。
Why Are Floating Point Numbers Inaccurate?
有一种非常自然的方法可以检查两个简单分数的值是否相等,而无需将它们转换为浮点数。
如果a/b = c/d
,则ad = bc
(b
或d
=0除外),所以:
boolean equals(Fraction other) {
if (this.denominator == 0 || other.denominator == 0)
return false; // undefined
return this.numerator * other.denominator == other.numerator * this.denominator;
}