小数を分数に変換するために必要なもの。 10フィートに変換するのは簡単です。
1.5 => 15/10
これは次のコードで実行できます。
public class Rational {
private int num, denom;
public Rational(double d) {
String s = String.valueOf(d);
int digitsDec = s.length() - 1 - s.indexOf('.');
int denom = 1;
for (int i = 0; i < digitsDec; i++) {
d *= 10;
denom *= 10;
}
int num = (int) Math.round(d);
this.num = num;
this.denom = denom;
}
public Rational(int num, int denom) {
this.num = num;
this.denom = denom;
}
public String toString() {
return String.valueOf(num) + "/" + String.valueOf(denom);
}
public static void main(String[] args) {
System.out.println(new Rational(1.5));
}
}
しかし、私が欲しいのは
1.5 => 3/2
どうすればいいのかわかりません。私の質問は重複ではありません。他の関連する質問はC#だからです。これはJavaです。
結果の数値の最大公約数を見つけて、分子と分母をそれで除算する必要があります。
これを行う1つの方法を次に示します。
public class Rational {
private int num, denom;
public Rational(double d) {
String s = String.valueOf(d);
int digitsDec = s.length() - 1 - s.indexOf('.');
int denom = 1;
for (int i = 0; i < digitsDec; i++) {
d *= 10;
denom *= 10;
}
int num = (int) Math.round(d);
int g = gcd(num, denom);
this.num = num / g;
this.denom = denom /g;
}
public Rational(int num, int denom) {
this.num = num;
this.denom = denom;
}
public String toString() {
return String.valueOf(num) + "/" + String.valueOf(denom);
}
public static int gcd(int num, int denom) {
....
}
public static void main(String[] args) {
System.out.println(new Rational(1.5));
}
}
static private String convertDecimalToFraction(double x){
if (x < 0){
return "-" + convertDecimalToFraction(-x);
}
double tolerance = 1.0E-6;
double h1=1; double h2=0;
double k1=0; double k2=1;
double b = x;
do {
double a = Math.floor(b);
double aux = h1; h1 = a*h1+h2; h2 = aux;
aux = k1; k1 = a*k1+k2; k2 = aux;
b = 1/(b-a);
} while (Math.abs(x-h1/k1) > x*tolerance);
return h1+"/"+k1;
}
こちら からこの回答を得ました。私がしなければならなかったのは、彼の答えをJavaに変換することだけです。
Double x> = 0、int p、int qが与えられた場合、p/qを最も近い近似として見つけます。
したがって(テストされていません):
public static Rational toFraction(double x) {
// Approximate x with p/q.
final double eps = 0.000_001;
int pfound = (int) Math.round(x);
int qfound = 1;
double errorfound = Math.abs(x - pfound);
for (int q = 2; q < 100 && error > eps; ++q) {
int p = (int) (x * q);
for (int i = 0; i < 2; ++i) { // below and above x
double error = Math.abs(x - ((double) p / q));
if (error < errorfound) {
pfound = p;
qfound = q;
errorfound = error;
}
++p;
}
}
return new Rational(pfound, qfound);
}
Math.PIとEで試すことができます。
この問題の解決策を用意しました。多分それは原始的なように見えますが、機能しています。多くの10進数をテストしました。少なくとも1.5を3/2に変換できます:)
public String kesirliYap(Double sayi){
String[] a=payPaydaVer(sayi);
return a[0]+"/"+a[1];
}
public String[] payPaydaVer(Double sayi){
long pay;
long payda;
DecimalFormat df=new DecimalFormat("#");
df.setRoundingMode(RoundingMode.FLOOR);
String metin=sayi.toString();
int virguldenSonra=(metin.length() -metin.indexOf("."))-1;
double payyda=Math.pow(10,virguldenSonra);
double payy=payyda*sayi;
String pays=df.format(payy);
String paydas=df.format(payyda);
pay=Long.valueOf(pays);
payda=Long.valueOf(paydas);
String[] kesir=sadelestir(pay,payda).split(",");
return kesir;
}
private String sadelestir(Long pay,Long payda){
DecimalFormat df=new DecimalFormat("#");
df.setRoundingMode(RoundingMode.FLOOR);
Long a=pay<payda ? pay : payda;
String b = "",c = "";
int sayac=0;
for(double i = a;i>1;i--){
double payy=pay/i;
double paydaa=payda/i;
String spay=df.format(payy);
String spayda=df.format(paydaa);
Long lpay=Long.valueOf(spay);
Long lpayda=Long.valueOf(spayda);
if((payy-lpay)==0&&(paydaa-lpayda)==0){
b=df.format(pay/i);
c=df.format(payda/i);
sayac++;
break;
}
}
return sayac>0 ? b+","+c:pay+","+payda;
}
ここに簡単なアルゴリズムがあります:
_numerato = 1.5
denominator = 1;
while (!isInterger(numerator*denominator))
do
denominator++;
done
return numerator*denominator + '/' + denominator
// => 3/2
_
Java + isInteger(i)
を実装する必要があります。ここで、i
はfloat
です。
10進数_1.5
_だけでなく、次の手順を使用できます。
小数桁数を検索:
_double d = 1.5050;//Example I used
_
_double d1 = 1;
_
String text = Double.toString(Math.abs(d));
int integerPlaces = text.indexOf('.');
int decimalPlaces = text.length() - integerPlaces - 1;
System.out.println(decimalPlaces);//4
次に整数に変換します:
static int ipower(int base, int exp) {
_ int result = 1;
for (int i = 1; i <= exp; i++) {
result *= base;
}
return result;
}
_
_//using the method
_
int i = (int) (d*ipower(10, decimalPlaces));
int i1 = (int) (d1*ipower(10, decimalPlaces));
System.out.println("i=" + i + " i1 =" +i1);//i=1505 i1 =1000
次に、最も高い共通因子を見つけます
private static int commonFactor(int num, int divisor) {
_ if (divisor == 0) {
return num;
}
return commonFactor(divisor, num % divisor);
}
_
_//using common factor
_
int commonfactor = commonFactor(i, i1);
System.out.println(commonfactor);//5
最後に結果を印刷します。
System.out.println(i/commonfactor + "/" + i1/commonfactor);//301/200
ここで見つけることができます:
_ public static void main(String[] args) {
double d = 1.5050;
double d1 = 1;
String text = Double.toString(Math.abs(d));
int integerPlaces = text.indexOf('.');
int decimalPlaces = text.length() - integerPlaces - 1;
System.out.println(decimalPlaces);
System.out.println(ipower(10, decimalPlaces));
int i = (int) (d*ipower(10, decimalPlaces));
int i1 = (int) (d1*ipower(10, decimalPlaces));
System.out.println("i=" + i + " i1 =" +i1);
int commonfactor = commonFactor(i, i1);
System.out.println(commonfactor);
System.out.println(i/commonfactor + "/" + i1/commonfactor);
}
static int ipower(int base, int exp) {
int result = 1;
for (int i = 1; i <= exp; i++) {
result *= base;
}
return result;
}
private static int commonFactor(int num, int divisor) {
if (divisor == 0) {
return num;
}
return commonFactor(divisor, num % divisor);
}
_
これを編集として追加しようとしましたが、拒否されました。この回答は、@ Hristo93の answer を基に構築されていますが、gcdメソッドを終了します。
public class DecimalToFraction {
private int numerator, denominator;
public Rational(double decimal) {
String string = String.valueOf(decimal);
int digitsDec = string.length() - 1 - s.indexOf('.');
int denominator = 1;
for (int i = 0; i < digitsDec; i++) {
decimal *= 10;
denominator *= 10;
}
int numerator = (int) Math.round(decimal);
int gcd = gcd(numerator, denominator);
this.numerator = numerator / gcd;
this.denominator = denominator /gcd;
}
public static int gcd(int numerator, int denom) {
return denominator == 0 ? numerator : gcm(denominator, numerator % denominator);
}
public String toString() {
return String.valueOf(numerator) + "/" + String.valueOf(denominator);
}
public static void main(String[] args) {
System.out.println(new Rational(1.5));
}
}
最高の共通因子を見つけるメソッドとtoStringメソッドを変更するメソッドを含めると、私はあなたの疑問を解決します。
public String toString() {
int hcf = findHighestCommonFactor(num, denom);
return (String.valueOf(num/hcf) + "/" + String.valueOf(denom/hcf));
}
private int findHighestCommonFactor(int num, int denom) {
if (denom == 0) {
return num;
}
return findHighestCommonFactor(denom, num % denom);
}
まず、10進数を変換する場合は、変換する前に状況の状態を知る必要があります。0.333333があり、3が無限に繰り返されているとしましょう。 0.333333が1/3であることは誰でも知っています。一部の人々は、小数点以下の桁数を乗算すると、それが変換されると考えています。それは完全に誤りです。これは関連する数学です。別の状況は0.25で、小数点以下の数値を100で除算して単純化します。これは1/4に等しく、完全に当てはまります。
ただし、数学では10進数を分数に変換する状況が3つあります。多くのスペースと時間がかかるため、説明しません。この問題のプログラムは既に作成しています。これはコードです:
import Java.math.BigDecimal;
import Java.math.BigInteger;
public class Main {
static BigDecimal finalResult = new BigDecimal("0");
static boolean check(short[] checks) {
boolean isContinues = true;
int index = -1;
for (short ind : checks) {
index++;
if (ind==1) {
}
else if (ind==0) {
isContinues = false;
break;
}
else if (ind==-1) {
if (index==0) {
isContinues = false;
}
break;
}
}
return isContinues;
}
static int[] analyzeDecimal() { // will return int[3]
int[] analysis = new int[3];
int dot = finalResult.toString().indexOf(".");
String num = finalResult.toString();
int state = -1;
int firstPart = 0; // first part will be compared with each secondPart!
int secondPart = 0;
String part = ""; // without the dot
int index = 0; // index for every loop!
int loop = 6;
int originalLoop = loop;
int size = 0; // until six!
int ps = -1;
short[] checks = new short[] {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1}; // 10 compares for each part!
// length of checks is 10!
int continues = -1; // -1 means there is no continues part!
boolean stop = false;
while (true) { // while for size!
if (size!=6) {
while (true) { // we need to compare a part with a part!
// while for loop
// 6 loops, every loop will increase the compared part by 1!
if (loop!=-1) { // TODO : check every part with the increasing pos
firstPart = dot+1+(originalLoop-loop); // changed
try {
part = num.substring(firstPart, firstPart+(size+1));
}
catch (StringIndexOutOfBoundsException ex) {
break;
}
int partSize = part.length();
int afterDecimal = num.length()-(dot+1);
while (index!=checks.length &&
firstPart+partSize+index*partSize-(dot+1)<=afterDecimal) { // while for index!
secondPart = firstPart+partSize+index*partSize;
String comparedPart;
try {
comparedPart = num.substring(secondPart, secondPart+partSize);
}
catch (StringIndexOutOfBoundsException ex) {
break;
}
if (part.equals(comparedPart)) {
checks[index] = 1;
}
else {
checks[index] = 0;
}
index++;
}
index = 0;
if (check(checks)) {
stop = true;
continues = firstPart;
ps = partSize;
}
for (int i = 0 ; i!=10 ; i++) {
checks[i] = -1;
}
}
else { // finished!
break;
}
loop--;
if (stop) {
break;
}
}
loop = originalLoop;
size++;
if (stop) {
break;
}
}
else {
break;
}
}
if (continues==-1) {
state = 2;
}
else {
if (dot+1==continues) {
state = 1;
}
else {
state = 0;
}
}
analysis[0] = state;
analysis[1] = continues;
analysis[2] = ps;
return analysis;
}
static String convertToStandard() {
// determine the state first :
int[] analysis = analyzeDecimal();
int dot = finalResult.toString().indexOf('.')+1;
int continues = analysis[1];
int partSize = analysis[2]; // how many steps after the continues part
if (analysis[0]==0) { // constant + continues
String number = finalResult.toString().substring(0, continues+partSize);
int numOfConst = continues-dot;
int numOfDecimals = continues+partSize-dot;
int den = (int)(Math.pow(10, numOfDecimals)-Math.pow(10, numOfConst)); // (10^numOfDecimals)-(10^numOfConst);
int num;
int toSubtract = Integer.parseInt(number.substring(0, dot-1)+number.substring(dot, dot+numOfConst));
if (number.charAt(0)==0) {
num = Integer.parseInt(number.substring(dot));
}
else {
num = Integer.parseInt(number.replace(".", ""));
}
num -= toSubtract;
return simplify(num, den);
}
else if (analysis[0]==1) { // continues
int num, den;
// we always have to subtract by only one x!
String n = finalResult.toString().substring(0, dot+partSize).replace(".", "");
num = Integer.parseInt(n);
den = nines(partSize);
int toSubtract = Integer.parseInt(finalResult.toString().substring(0, dot-1));
num -= toSubtract;
return simplify(num, den);
}
else if (analysis[0]==2) { // constant
partSize = finalResult.toString().length()-dot;
int num = Integer.parseInt(finalResult.toString().replace(".", ""));
int den = (int)Math.pow(10, partSize);
return simplify(num, den);
}
else {
System.out.println("[Error] State is not determined!");
}
return "STATE NOT DETERMINED!";
}
static String simplify(int num, int den) {
BigInteger n1 = new BigInteger(Integer.toString(num));
BigInteger n2 = new BigInteger(Integer.toString(den));
BigInteger GCD = n1.gcd(n2);
String number = Integer.toString(num/GCD.intValue())+"/"+Integer.toString(den/GCD.intValue());
return number;
}
static int nines(int n) {
StringBuilder result = new StringBuilder();
while (n!=0) {
n--;
result.append("9");
}
return Integer.parseInt(result.toString());
}
public static void main(String[] args) {
finalResult = new BigDecimal("1.222222");
System.out.println(convertToStandard());
}
}
上記のプログラムは、高精度で最適な結果を提供します。メイン関数のfinalResult変数を変更するだけです。