将小数转换为分数
Converting decimal to fraction
我有一种方法可以将小数(双精度值)转换为分数并将分子和分母值放入大小为 2 的 int[] 中。
除了我点击 0.0001
之外,大多数值的测试结果都很好。那么return值为1.0/1.0
.
方法:
private static int[] toFractionPos(double x){
String[] parts = Double.toString(x).split("\.");
double den = Math.pow(10, parts[1].length()); //denominator
double num = Double.parseDouble(parts[0]) * den + Double.parseDouble(parts[1]); //numerator
return reduceFraction((int)num, (int)den);
}
reduceFraction()
方法:
public static int[] reduceFraction(int num, int den){
int gcf = GCF(num, den); //greatest common factor
int[] rf = {num/gcf, den/gcf};
return rf;
}
谢谢!
算法看起来不错。但是,使用double
不适合这类问题,因为精度会随着规模的增长而降低。
您应该改用 BigDecimal
and BigInteger
。我粗略地修改了您的示例,以便它可以与它们一起使用,但我没有处理细节,即解析 String
应该不是必需的,因为可以从 BigDecimal
中检索比例a getter,可以配置不同的舍入模式等:
import java.math.BigDecimal;
import java.math.BigInteger;
public class Sample {
static int[] toFractionPos(BigDecimal x) {
String[] parts = x.toString().split("\.");
BigDecimal den = BigDecimal.TEN.pow(parts[1].length()); // denominator
BigDecimal num = (new BigDecimal(parts[0]).multiply(den)).add(new BigDecimal(parts[1])); // numerator
return reduceFraction(num.intValue(), den.intValue());
}
static int[] reduceFraction(int num, int den) {
int gcd = BigInteger.valueOf(num).gcd(BigInteger.valueOf(den)).intValue(); // greatest
// common
// divisor
int[] rf = { num / gcd, den / gcd };
return rf;
}
public static void main(String[] args) {
int[] fraction = toFractionPos(new BigDecimal("0.0001"));
System.out.println(fraction[0] + "/" + fraction[1]); // 1/10000
}
}
注意: 优化留作练习 ;)
你不应该使用双打,因为你会失去精度,这会导致严重的错误。但在 1.0001
的情况下,问题是:
Double.toString(1.0001) == "1.0E-4"
然后您尝试解析 "0E-4"
并得到 0 而不是 1。如果您希望最多有 10 个小数点,您可以执行以下操作:
DecimalFormat df = new DecimalFormat("0",
DecimalFormatSymbols.getInstance(Locale.ENGLISH));
df.setMaximumFractionDigits(10);
String[] parts = df.format(x).split("\.");
这个怎么样?
private static int[] toFractionPos(double x){
int den = (int)Math.pow(10,(int)Math.log10(Integer.MAX_VALUE));
int num = (int)(x*den);
return reduceFraction(num, den);//this came from your code
}
我认为这会奏效,
public int[] Fraction(double n) {
BigDecimal p = BigDecimal.ONE;
BigDecimal dn = BigDecimal.valueOf(n);
while(true){
dn = dn.multiply(p);
if( dn.compareTo(new BigDecimal(dn.toBigInteger()))==0 )
break;
else
p = p.multiply(BigDecimal.TEN);
}
BigInteger num=dn.toBigInteger(), den=p.toBigInteger(), g=num.gcd(den);
num = num.divide(g);
den = den.divide(g);
int[] res = new int[2];
res[0] = num.intValue();
res[0] = den.intValue();
return res;
}
我有一种方法可以将小数(双精度值)转换为分数并将分子和分母值放入大小为 2 的 int[] 中。
除了我点击 0.0001
之外,大多数值的测试结果都很好。那么return值为1.0/1.0
.
方法:
private static int[] toFractionPos(double x){
String[] parts = Double.toString(x).split("\.");
double den = Math.pow(10, parts[1].length()); //denominator
double num = Double.parseDouble(parts[0]) * den + Double.parseDouble(parts[1]); //numerator
return reduceFraction((int)num, (int)den);
}
reduceFraction()
方法:
public static int[] reduceFraction(int num, int den){
int gcf = GCF(num, den); //greatest common factor
int[] rf = {num/gcf, den/gcf};
return rf;
}
谢谢!
算法看起来不错。但是,使用double
不适合这类问题,因为精度会随着规模的增长而降低。
您应该改用 BigDecimal
and BigInteger
。我粗略地修改了您的示例,以便它可以与它们一起使用,但我没有处理细节,即解析 String
应该不是必需的,因为可以从 BigDecimal
中检索比例a getter,可以配置不同的舍入模式等:
import java.math.BigDecimal;
import java.math.BigInteger;
public class Sample {
static int[] toFractionPos(BigDecimal x) {
String[] parts = x.toString().split("\.");
BigDecimal den = BigDecimal.TEN.pow(parts[1].length()); // denominator
BigDecimal num = (new BigDecimal(parts[0]).multiply(den)).add(new BigDecimal(parts[1])); // numerator
return reduceFraction(num.intValue(), den.intValue());
}
static int[] reduceFraction(int num, int den) {
int gcd = BigInteger.valueOf(num).gcd(BigInteger.valueOf(den)).intValue(); // greatest
// common
// divisor
int[] rf = { num / gcd, den / gcd };
return rf;
}
public static void main(String[] args) {
int[] fraction = toFractionPos(new BigDecimal("0.0001"));
System.out.println(fraction[0] + "/" + fraction[1]); // 1/10000
}
}
注意: 优化留作练习 ;)
你不应该使用双打,因为你会失去精度,这会导致严重的错误。但在 1.0001
的情况下,问题是:
Double.toString(1.0001) == "1.0E-4"
然后您尝试解析 "0E-4"
并得到 0 而不是 1。如果您希望最多有 10 个小数点,您可以执行以下操作:
DecimalFormat df = new DecimalFormat("0",
DecimalFormatSymbols.getInstance(Locale.ENGLISH));
df.setMaximumFractionDigits(10);
String[] parts = df.format(x).split("\.");
这个怎么样?
private static int[] toFractionPos(double x){
int den = (int)Math.pow(10,(int)Math.log10(Integer.MAX_VALUE));
int num = (int)(x*den);
return reduceFraction(num, den);//this came from your code
}
我认为这会奏效,
public int[] Fraction(double n) {
BigDecimal p = BigDecimal.ONE;
BigDecimal dn = BigDecimal.valueOf(n);
while(true){
dn = dn.multiply(p);
if( dn.compareTo(new BigDecimal(dn.toBigInteger()))==0 )
break;
else
p = p.multiply(BigDecimal.TEN);
}
BigInteger num=dn.toBigInteger(), den=p.toBigInteger(), g=num.gcd(den);
num = num.divide(g);
den = den.divide(g);
int[] res = new int[2];
res[0] = num.intValue();
res[0] = den.intValue();
return res;
}