java - 带有简化分数的分数计算器
问题描述
我的代码有几个问题,虽然我已经尝试过了,但我还没有发现它有什么问题。这里是:
public class FracCalc {
public static void main(String[] args) {
// String to test
//String input = "5_3/4 - 6_7/8 + 3/4";
System.out.println(produceAnswer("-3_3/4 / -2_2/3"));
}
public static String produceAnswer(String input) {
// Splits everything at every space
String[] array = input.split(" ", 0);
int allWholes = 0;
int allNumerators = 0;
int allDenominators = 1;
// Multiplier is 1 or -1, 1 is add, -1 is subtract
int multiplier = 1;
// Operation mode; 0=+,-; 1=*; 2=/
int mode = 0;
// the for loop is used to identify and solve the the test
for (int i = 0; i < array.length; i++) {
String part = array[i];
//
int whole = 0;
int numerator = 0;
int denominator = 0;
// If it has a _, then it's a whole + fraction
if (part.contains("_")) {
// Convert Int from start of part (0) to the character before _, "55_30/40" -> 55
whole = Integer.parseInt(part.substring(0, part.indexOf("_")));
// Convert Int from the character AFTER _ to the character before /, "55_30/40" -> 30
numerator = Integer.parseInt(part.substring(part.indexOf("_") + 1, part.indexOf("/")));
// Convert Int from the character AFTER / to the end, "55_30/40" -> 40
denominator = Integer.parseInt(part.substring(part.indexOf("/") + 1, part.length()));
}
// If no _, but still has a / AND it is not just the symbol "/", then it's just a fraction
else if (part.contains("/") && part.length() != 1) {
numerator = Integer.parseInt(part.substring(0, part.indexOf("/")));
denominator = Integer.parseInt(part.substring(part.indexOf("/") + 1, part.length()));
} //else if(part.contains("*") && part.contains("/")){}
else if (part.contains("/") ) {
mode = 2;
}
// TODO: Make multiplication
// Negative sign(if number is negative)
else if (part.contains("-")) {
multiplier = -1;
}
// Positive sign(if number is positive)
else if (part.contains("+")) {
multiplier = 1;
}
// If neither _ nor /, then it's a whole
else {
whole = Integer.parseInt(part);
}
// Add all the wholes together
allWholes += whole * multiplier;
// If denom is the same
if (denominator == allDenominators) {
allNumerators += numerator * multiplier;
}
// If they're not the same
else if (numerator != 0 && denominator != 0) {
if (mode == 0 ) {
// Cross multiply
allNumerators *= denominator;
// Add
allNumerators += numerator * allDenominators * multiplier;
// Second part of cross multiply
allDenominators *= denominator;
}
// Multiplication
else if (mode == 1) {
allDenominators *= denominator;
allNumerators *= numerator;
}
// Division
else if (mode == 2) {
// Reverse multiply because (1/2)/(1/2) -> (1*1)/(2*2)
allNumerators = allNumerators * denominator;
allDenominators = allDenominators * numerator;
}
}
}
// Simplifies fraction by checking to see id the top is bigger than bottom
// 9/4 -> 2_1/4
while(allNumerators > allDenominators){
allWholes = allNumerators / allDenominators;
allNumerators %= allDenominators;
}
if (allWholes == 0) {
return (allNumerators + "/" + allDenominators);
}
else if (allNumerators == 0 || allDenominators == 0) {
return allWholes + "";
}
else {
return allWholes + "_" + (allNumerators + "/" + allDenominators);
}
}
}
我的目标是制作一个带有简化答案的分数计算器(作为分数)。我很确定我的乘法、除法和简化 while 循环是问题所在。谢谢!
解决方案
您的代码中有很多好的想法,但正如您所知,也存在问题。
试图跟踪计算中的整个部分会遇到很多麻烦。就像在小学数学中一样,使用整个部分来创建一个不正确的分数,方法是:
numerator += whole*denominator;
然后只需使用
numerator
and进行数学运算,denominator
并在完成所有计算后提取整个部分,您已经在执行此操作。你解析负数的方式是错误的。此外,您应该删除使用
multiplier
并只使用负数numerator
。如果您删除
multiplier
,那么您需要跟踪-
并+
作为单独的操作,但这很容易做到。在每次计算结束时,您应该通过以下方式确保结果
allDenominators
为正:if (allDenominators < 0) { allNumerators = -allNumerators; allDenominators = -allDenominators; }
这将阻止您输出 -3/-4
简化分数的方式并不完全正确。你有:
while(allNumerators > allDenominators){ allWholes = allNumerators / allDenominators; allNumerators %= allDenominators; }
如果
allNumerators == allDenominators
,即答案应该是 1 怎么办?此外,一旦你完成allNumerators %= allDenominators
了 while 循环中的条件,就不再是真的。只需这样做:if(allNumerators >= allDenominators){ allWholes = allNumerators / allDenominators; allNumerators %= allDenominators; }
最后考虑实现一个更大的公约数(GCD)例程来简化你的分数,例如从
48/128
到3/8
这是您的代码副本,其中包含上述大部分想法,但您可能应该先尝试自己修复它们,并且仅将其用作参考。
public class FracCalc
{
public static void main(String[] args)
{
// String to test
System.out.println(produceAnswer("5_3/4 - 6_7/8 + 3/4"));
System.out.println(produceAnswer("-3_3/4 / -2_2/3"));
}
public static String produceAnswer(String input)
{
// Splits everything at every space
String[] array = input.split(" ", 0);
int allNumerators = 0;
int allDenominators = 1;
// Operation mode; 0=+; 1=-; 2=*; 3=/
int mode = 0;
// the for loop is used to identify and solve the the test
for (int i = 0; i < array.length; i++)
{
String part = array[i];
int numerator = 0;
int denominator = 0;
// If it has a _, then it's a whole + fraction
if (part.contains("_"))
{
// Convert Int from start of part (0) to the character before _,
// "55_30/40" -> 55
int whole = Integer.parseInt(part.substring(0, part.indexOf("_")));
// Convert Int from the character AFTER _ to the character before /,
// "55_30/40" -> 30
numerator = Integer.parseInt(part.substring(part.indexOf("_") + 1, part.indexOf("/")));
// Convert Int from the character AFTER / to the end, "55_30/40" -> 40
denominator = Integer.parseInt(part.substring(part.indexOf("/") + 1, part.length()));
if (whole > 0)
numerator += whole * denominator;
else
numerator = -numerator + whole * denominator;
}
// If no _, but still has a / AND it is not just the symbol "/", then it's
// just a fraction
else if (part.contains("/") && part.length() != 1)
{
numerator = Integer.parseInt(part.substring(0, part.indexOf("/")));
denominator = Integer.parseInt(part.substring(part.indexOf("/") + 1, part.length()));
} // else if(part.contains("*") && part.contains("/")){}
else if (part.equals("/"))
{
mode = 3;
}
else if (part.equals("+"))
{
mode = 0;
}
else if (part.equals("-"))
{
mode = 1;
}
else if (part.equals("*"))
{
mode = 2;
}
// If neither _ nor /, then it's a whole
else
{
numerator = Integer.parseInt(part);
denominator = 1;
}
if (numerator != 0 && denominator != 0)
{
if (mode < 2)
{
if (denominator == allDenominators)
{
allNumerators += numerator;
}
else
{
// Cross multiply
allNumerators *= denominator;
if (mode == 0)
{
// Add
allNumerators += numerator * allDenominators;
}
else
{
// Sub
allNumerators -= numerator * allDenominators;
}
// Second part of cross multiply
allDenominators *= denominator;
}
}
// Multiplication
else if (mode == 2)
{
allDenominators *= denominator;
allNumerators *= numerator;
}
// Division
else if (mode == 3)
{
// Reverse multiply because (1/2)/(1/2) -> (1*1)/(2*2)
allNumerators = allNumerators * denominator;
allDenominators = allDenominators * numerator;
}
// make sure denominators are +ve
if (allDenominators < 0)
{
allNumerators = -allNumerators;
allDenominators = -allDenominators;
}
}
}
// Simplifies fraction by checking to see id the top is bigger than bottom
// 9/4 -> 2_1/4
int allWholes = 0;
if (allNumerators >= allDenominators)
{
allWholes = allNumerators / allDenominators;
allNumerators %= allDenominators;
}
// consider implementing GCD to reduce num/den to simplest form
if (allWholes == 0)
{
return (allNumerators + "/" + allDenominators);
}
else if (allNumerators == 0 || allDenominators == 0)
{
return allWholes + "";
}
else
{
return allWholes + "_" + (allNumerators + "/" + allDenominators);
}
}
}
输出:
-48/128
1_13/32
我认为这是正确的答案。顺便说一句,Symbolab有一个很棒的工具,可以让您输入包含分数的表达式,以便您检查结果。
推荐阅读
- swashbuckle - 使用 Swashbuckle.AspNetCore 手动将自定义路由参数添加到 Swagger 文档
- excel - Excel - 创建数据透视表时避免计算 0
- arrays - Groovy 字典映射 - 如何根据映射的键值排序 - 如果值是 xxxx 格式 - 使用 . 字符
- sql - SQL Server - 如何检查同一表的其他行中是否不存在相同列值的值?
- scala - 将 RDD[(String,Map[String,Int])] 展平为 RDD[String,String,Int]
- amazon-web-services - 当我们保存文件时,s3 会自己创建对象吗?
- python - python列表附加值取决于if子句
- android - 再次从 RXJava 中的 onError 回调开始重新订阅 Observable 的 Retrofit 调用
- oracle - SWIFT MT 940 解析器/转换器
- java - java用皮秒解析日期