Java get fraction method - java

I am trying to make a method that returns the fractional value of a decimal number.
//these are included in a class called 'equazioni'
private static long getMCD(long a, long b) {
if (b == 0)
{ return a; }
else
{ getMCD(b, a % b); }
}
public String getFraction(double a) {
String s = String.valueOf(a);
int decimali = s.length() - 1 - s.indexOf('.');
int den = 1;
for(int i = 0; i < decimali; i++){
a *= 10;
den *= 10;
}
int num = (int) Math.round(a);
long mcd = getMCD(num,den);
return String.valueOf(num/mcd) + "/" + String.valueOf(den/mcd);
}
These 2 methods works perfectly with most of values. For example with a 8.65 it returns a 173/20, or 78.24 it returns a 1956/25. It's called in this way:
equazioni eq = new equazioni(a,b,c);
jTextField4.setText("8.65= " + eq.getFraction(8.65));
I am having troubles with fractions like 2/3, 5/18, 6/45... because the denominator is divisible by 3 and so the fraction is a periodic number. How could I represent it?
My problem is also "How could I recognize that it's a periodic number?". I thought that I could something like this
int test = den % 3;
If the denominator is divisible by 3, then I have to generate a fraction in a particular way. Any suggestion?

If I correctly understood your question, I am afraid it does not have a complete solution. Since a float is stored with a finite number of bits, not all fractions can be represented, especially the ones that are not decimal numbers like 2/3. Even for decimal numbers, not all of them can be represented.
In other words, your method will never be called by the float representation of 2/3 as an input, since this representation does not exist. You might be called with 0.66666666 (with whatever the limit of digits would be in Java), but that is not 2/3...
See this link for more details about floating point representation in Java: http://introcs.cs.princeton.edu/java/91float/

Related

Java Fraction Base Conversion [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 3 years ago.
Improve this question
I want to convert a source base number to a destination base number, but I have a problem with fractions. When I trying to convert 10.234 (base10) to base 7 = 13.14315 it works perfectly, or aaaaa.0 (base16) to base 24 = 22df2 it also works.
But when I try to convert aaaaa.cdefb0 (base16) to base 24 = 22df2.j78da it doesn't work. I can't calculate fraction part and I get 22df2 as the answer
my code for base conversion :
private static String baseConversion(String number,
int sBase, int dBase) {
return Long.toString(
Long.parseLong(number, sBase),
dBase);
}
my code for fraction conversion :
private static String fractionConversion(double fraction, int dBase) {
StringBuilder output = new StringBuilder(".");
for (int i = 0; i < PRECISION; i++) {
fraction *= dBase;
output.append(Long.parseLong(Integer.toString((int) fraction)));
fraction -= Long.parseLong(Integer.toString((int) fraction));
}
return output.toString();
}
In your code below you should be appending a symbol for the base, not a number. Use the number to index into an array of symbols for the base.
And I recommend using integers for your remainder and product computations as you will eventually lose precision using floating point values.
for (int i = 0; i < PRECISION; i++) {
fraction *= dBase;
// what are you appending here? It should be a symbol
output.append(Long.parseLong(Integer.toString((int) fraction)));
fraction -= Long.parseLong(Integer.toString((int) fraction));
}
Here's a more complete example.
static String symbols = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
// assumes a string in the form of .293093
// number of places
// destination radix.
public static String expand(String decimalFraction, int places, int dr) {
decimalFraction = decimalFraction.substring(1); // ignore decimal point
int numerator = Integer.parseInt(decimalFraction);
int denominator = (int) Math.pow(10, decimalFraction.length());
StringBuilder sb = new StringBuilder(".");
for (int i = 0; i < places; i++) {
numerator *= dr;
sb.append(symbols.charAt((int) (numerator / denominator)));
numerator %= denominator;
if (numerator == 0) {
break;
}
}
return sb.toString();
}
I earnestly cannot recommend doing this, but I'll answer the question anyhow.
I would simply split the two numbers and treat them separately. First and foremost, how fractions work outside of Base 10 is not a 1-for-1 conversion of the trailing number. .25 in base 10 is not .11001 in binary, it's .01.
Every decimal place in your number represents a new magnitude; in base 10 it's values of 10^-1, 10^-2, and so on. When you change bases, you still change magnitudes but at different rates: 2^-1, etc.
.25 is thus analogous to 2/10 + 5/100 in base 10, and 0/2 + 1/4 in base 2. This leads to a new problem, where if the divisor of a fraction isn't a power of your new base, you usually get an irrational number. 1/20 is .05 in decimal, but in base 2 it's:
0.00 0011 0011 0011 //endless
This more or less leads to why fractional numbers are not normally converted between bases. You will lose precision and it's not a small task. But essentially the algorithmic conversation is the same as for whole numbers, but instead of dividing the number by the base and using the remainder as your output, you multiply by the base and use the division as your output.
int decimalPart = ...; //for example, "375", represents .375 or 3/8
int magnitude = Math.pow(10, ("" + decimalPart).length());
int newBase = 2; //again, bases that don't divide into each other will be messy, like 7 and 10
StringBuilder out = new StringBuilder();
//The below should be limited for precision, or you may loop forever
while (decimalPart > 0) {
decimalPart *= newBase;
out.append(decimalPart / magnitude);
decimalPart %= magnitude.
}
String result = sb.toString();
//"375" -> "011"

why does modulus by a large number seem to give a wrong answer in Java

I am trying to find trailing numbers of zeros in a number, here is my code:
public class TrailingZeroes {
public static void bruteForce(int num){ //25
double fact = num; //25
int numOfZeroes = 0;
for(int i= num - 1; i > 1; i--){
fact = fact * (i);
}
System.out.printf("Fact: %.0f\n",fact); //15511210043330984000000000
while(fact % 10 == 0){
fact = fact / 10;
double factRem = fact % 10;
System.out.printf("Fact/10: %.0f\n",fact); //1551121004333098400000000
System.out.printf("FactRem: %.0f\n",factRem); // 2?
numOfZeroes++;
}
System.out.println("Nnumber of zeroes "+ numOfZeroes); //1
}
}
As you can see the fact%10
You use floating point data type illegally.
The float and double primitive types in Java are floating point numbers, where the number is stored as a binary representation of a fraction and a exponent.
More specifically, a double-precision floating point value such as the double type is a 64-bit value, where:
1 bit denotes the sign (positive or negative).
11 bits for the exponent.
52 bits for the significant digits (the fractional part as a binary).
These parts are combined to produce a double representation of a value.
For a detailed description of how floating point values are handled in Java, see the Section 4.2.3: Floating-Point Types, Formats, and Values of the Java Language Specification.
The byte, char, int, long types are [fixed-point][6] numbers, which are exact representions of numbers. Unlike fixed point numbers, floating point numbers will some times (safe to assume "most of the time") not be able to return an exact representation of a number. This is the reason why you end up with 11.399999999999 as the result of 5.6 + 5.8.
When requiring a value that is exact, such as 1.5 or 150.1005, you'll want to use one of the fixed-point types, which will be able to represent the number exactly.
As has been mentioned several times already, Java has a BigDecimal class which will handle very large numbers and very small numbers.
public static void bruteForce(int num) { //25
double fact = num;
// precision was lost on high i
for (int i = num - 1; i > 1; i--)
fact *= i;
String str = String.format("%.0f", fact); //15511210043330984000000000
System.out.println(str);
int i = str.length() - 1;
int numOfZeroes = 0;
while (str.charAt(i--) == '0')
numOfZeroes++;
System.out.println("Number of zeroes " + numOfZeroes); //9
}

Integer division using recursion--and a few other interesting limitations

I am trying to solve a puzzle in Java for my own edification. I am told there is a solution by the guy who designed the puzzle, but I'm not able to find it myself.
Here's the puzzle:
Implement the following method in Java
/**
* Divides a natural number by two.
*
* #param n
* The number to be divided
* #updates n
* #ensures n = floor(n/2)
*/
private static void split(NaturalNumber n) {...}
The NaturalNumber class is simply a class that stores a natural number
using a string. ( That is, it can store numbers much larger than
Integer.MAX_VALUE. )
The class provides these instance methods and inherited
methods, as well as the NaturalNumber.isZero() method, which
returns true if the instance's internal string value is "0", false
otherwise.
It's worth noting that the NaturalNumber.divideBy10() method
essentially pops the rightmost digit off the number, returns it as an
int and updates the instance's internal value.
Do not use static properties on the main class to store values.
Similarly, do not write static helper methods.
Do not convert n to some other data type and operate on that. Do not use external libraries.
Furthermore, split() must be implemented using recursion.
I have the following near solution worked out:
private static void split(NaturalNumber n) {
// Initialize local variables.
String stringBuffer = "";
int numerator = 0;
int quotient = 0;
int remainder = 0;
int thisDigit = n.divideBy10();
if (n.isZero()) {
quotient = thisDigit / 2;
remainder = thisDigit % 2;
n.transferFrom(new NaturalNumber2(quotient * 10 + remainder));
} else {
split(n);
numerator = n.divideBy10() * 10 + thisDigit;
quotient = numerator / 2;
remainder = numerator % 2;
if (!n.isZero()) {
stringBuffer += n.toString();
}
stringBuffer += Integer.toString(quotient * 10 + remainder);
n.transferFrom(new NaturalNumber2(stringBuffer));
}
}
The above simply performs long division. But the last frame in the call stack needlessly appends the remainder of its operation onto the end of the solution.
I have seen solutions to similar problems that recursively subtract two from n, counting how many times two must be subtracted for n to become zero. But those solutions rely on the method having a return value; this puzzle requires there be no return value.
I can also see how to solve the puzzle using one function call to split() and internal loops. But I am told the solution must not rely on loops to operate on n.
Does anyone out there have any insight into a solution?
Suppose the digits of n are a...yz. If y is even, then the digits of n / 2 are the concatenation of a...y / 2 and z / 2. If y is odd, let Y = y - 1. Then the digits of n / 2 are the concatenation of a...Y / 2 and 1z / 2.
We can implement this as follows:
private static void split(NaturalNumber n) {
int z = n.divideBy10();
int y = n.divideBy10();
if (n.isZero()) {
// Base case.
int result = (y * 10 + z) / 2;
n.multiplyBy10(result / 10);
n.multiplyBy10(result % 10);
} else if (y % 2 == 0) {
n.multiplyBy10(y);
split(n);
n.multiplyBy10(z / 2);
} else {
n.multiplyBy10(y - 1);
split(n);
n.multiplyBy10((10 + z) / 2);
}
}
Incidentally, these method names are awful, and making NaturalNumbers mutable is a weird design choice.

How to convert decimal to a higher base and vice versa

As a programming assignment for my java CSC class I have written the following code to convert a number and its base to a decimal number and then to a desired number and base.
public static int baseten(int number,int basein){
int power = 0;
int baseten = 0;
while (number > 0) {
int finalDigit = number % 10;
int product = finalDigit*(int)Math.pow(basein, power);
baseten += product;
number = number / 10;
power++;
}
return(baseten);
}
public static String convert (int decimal, int baseout){
String result = "";
while (decimal > 0){
//if baseout
int remainder = decimal % baseout;
decimal = decimal / baseout;
result = remainder + result;
}
return(result);
}
The question is how to convert a number to a base higher than ten within this code? I assume maybe a char[], but I'm not very good with arrays right now and can't imagine what that might look like. I don't think I can use toString's or parseInt's. Any help would be appreciated. Thanks in advance.
You are almost there. What you could do is insert an if/else statement to determine whether the remainder is greater or equal to ten or not and act accordingly. If it isn't, do what you're doing right now. If it is, then you need to add a char to your string. This char must be (remainder-10) + 65, since 65 is capital A on the ascii table and you need to know how many digits above ten remainder is and add that to A. This could be simplified to simply adding 55, but that is less readable in my opinion. Then, just add that char to the string instead of adding the int.

Format Double as Fraction [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
We don’t allow questions seeking recommendations for books, tools, software libraries, and more. You can edit the question so it can be answered with facts and citations.
Closed 7 years ago.
Improve this question
Is there a library that will convert a Double to a String with the whole number, followed by a fraction?
For example
1.125 = 1 1/8
I am only looking for fractions to a 64th of an inch.
Your problem is pretty simple, because you're assured the denominator will always divide 64. in C# (someone feel free to translate a Java version):
string ToMixedFraction(decimal x)
{
int whole = (int) x;
int denominator = 64;
int numerator = (int)( (x - whole) * denominator );
if (numerator == 0)
{
return whole.ToString();
}
while ( numerator % 2 == 0 ) // simplify fraction
{
numerator /= 2;
denominator /=2;
}
return string.Format("{0} {1}/{2}", whole, numerator, denominator);
}
Bonus: Code Golf
public static string ToMixedFraction(decimal x) {
int w = (int)x,
n = (int)(x * 64) % 64,
a = n & -n;
return w + (n == 0 ? "" : " " + n / a + "/" + 64 / a);
}
One problem you might run into is that not all fractional values can be represented by doubles. Even some values that look simple, like 0.1. Now on with the pseudocode algorithm. You would probably be best off determining the number of 64ths of an inch, but dividing the decimal portion by 0.015625. After that, you can reduce your fraction to the lowest common denominator. However, since you state inches, you may not want to use the smallest common denominator, but rather only values for which inches are usually represented, 2,4,8,16,32,64.
One thing to point out however, is that since you are using inches, if the values are all proper fractions of an inch, with a denominator of 2,4,8,16,32,64 then the value should never contain floating point errors, because the denominator is always a power of 2. However if your dataset had a value of .1 inch in there, then you would start to run into problems.
How about org.apache.commons.math ? They have a Fraction class that takes a double.
http://commons.apache.org/math/api-1.2/org/apache/commons/math/fraction/Fraction.html
You should be able to extend it and give it functionality for the 64th. And you can also add a toString that will easily print out the whole number part of the fraction for you.
Fraction(double value, int
maxDenominator) Create a fraction
given the double value and maximum
denominator.
I don't necessarily agree, base on the fact that Milhous wants to cover inches up to 1/64"
Suppose that the program demands 1/64" precision at all times, that should take up 6 bits of the mantissa. In a float, there's 24-6 = 18, which (if my math is right), should mean that he's got a range of +/- 262144 + 63/64"
That might be enough precision in the float to convert properly into the faction without loss.
And since most people working on inches uses denominator of powers of 2, it should be fine.
But back to the original question, I don't know any libraries that would do that.
Function for this in a C-variant called LPC follows. Some notes:
Addition to input value at beginning is to try to cope with precision issues that otherwise love to wind up telling you that 5 is 4 999999/1000000.
The to_int() function truncates to integer.
Language has a to_string() that will turn some floats into exponential notation.
string strfrac(float frac) {
int main = to_int(frac + frac / 1000000.0);
string out = to_string(main);
float rem = frac - to_float(main);
string rep;
if(rem > 0 && (to_int(rep = to_string(rem)) || member(rep, 'e') == Null)) {
int array primes = ({ 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47 });
string base;
int exp;
int num;
int div;
if(sscanf(rep, "%se%d", base, exp) == 2) {
num = to_int(replace(base, ".", ""));
div = to_int(pow(10, abs(exp)));
} else {
rep = rep[2..];
num = to_int(rep);
div = to_int(pow(10, strlen(rep)));
}
foreach(int prime : primes) {
if(prime > num)
break;
while((num / prime) * prime == num && (div / prime) * prime == div) {
num /= prime;
div /= prime;
}
}
out += " " + num + "/" + div;
}
return out;
}
i wrote this for my project i hope it could be usefull:
//How to "Convert" double to fraction("a/b") - kevinlopez#unitec.edu
private boolean isInt(double number){
if(number%2==0 ||(number+1)%2==0){
return true;
}
return false;
}
private String doubleToFraction(double doub){
//we get the whole part
int whole = (int)doub;
//we get the rest
double rest = doub - (double)whole;
int numerator=1,denominator=1;
//if the whole part of the number is greater than 0
//we'll try to transform the rest of the number to an Integer
//by multiplying the number until it become an integer
if(whole >=1){
for(int i = 2; ; i++){
/*when we find the "Integer" number(it'll be the numerator)
* we also found the denominator(i,which is the number that transforms the number to integer)
* For example if we have the number = 2.5 when it is multiplied by 2
* now it's 5 and it's integer, now we have the numerator(the number (2.5)*i(2) = 5)
* and the denominator i = 2
*/
if(isInt(rest*(double)i)){
numerator = (int)(rest*(double)i);
denominator = i;
break;
}
if(i>10000){
//if i is greater than 10000 it's posible that the number is irrational
//and it can't be represented as a fractional number
return doub+"";
}
}
//if we have the number 3.5 the whole part is 3 then we have the rest represented in fraction 0.5 = 1/2
//so we have a mixed fraction 3+1/2 = 7/2
numerator = (whole*denominator)+numerator;
}else{
//If not we'll try to transform the original number to an integer
//with the same process
for(int i = 2; ; i++){
if(isInt(doub*(double)i)){
numerator = (int)(doub*(double)i);
denominator = i;
break;
}
if(i>10000){
return doub+"";
}
}
}
return numerator+"/"+denominator;
}
My code looks like this.
public static int gcd(int a, int b)
{
if (b == 0)
return a;
else
return gcd(b, a % b);
}
public static String doubleToStringFraction(Double d)
{
StringBuffer result = new StringBuffer(" " + ((int) Math.floor(d)));
int whole = (int) ((d - Math.floor(d)) * 10000);
int gcd = gcd(whole, 10000);
result.append(" " + (whole / gcd) + "/" + 10000 / gcd + " ");
return result.toString();
}
As several others have poited out, fractions of 64 can be precicely represented by IEEE-floats. This means we can also convert to a fraction by moving and masking bits.
This is not the place to explain all details of floating point representations, please refer to wikipedia for details.
Briefly: a floating point number is stored as (sign)(exp)(frac) where sign is 1 bit, exp is 11 bits and frac is the fraction part (after 1.) and is 52 bits. This is enterpreted as the number:
(sign == 1 ? -1 : 1) * 1.(frac) * 2^(exp-1023)
Thus, we can get the 64th by moving the point accoring to the exponent and masking out the 6 bits after the point. In Java:
private static final long MANTISSA_FRAC_BITMAP = 0xfffffffffffffl;
private static final long MANTISSA_IMPLICIT_PREFIX = 0x10000000000000l;
private static final long DENOM_BITMAP = 0x3f; // 1/64
private static final long DENOM_LEN = 6;
private static final int FRAC_LEN = 52;
public String floatAsFrac64(double d) {
long bitmap = Double.doubleToLongBits(d);
long mantissa = bitmap & MANTISSA_FRAC_BITMAP | MANTISSA_IMPLICIT_PREFIX;
long exponent = ((bitmap >> FRAC_LEN) & 0x7ff) - 1023;
boolean negative = (bitmap & (1l << 63)) > 0;
// algorithm:
// d is stored as SE(11)F(52), implicit "1." before F
// move point to the right <exponent> bits to the right:
if(exponent > FRAC_LEN) System.out.println("warning: loosing precision, too high exponent");
int pointPlace = FRAC_LEN-(int)exponent;
// get the whole part as the number left of the point:
long whole = mantissa >> pointPlace;
// get the frac part as the 6 first bits right of the point:
long frac = (mantissa >> (pointPlace-DENOM_LEN)) & DENOM_BITMAP;
// if the last operation shifted 1s out to the right, we lost precision, check with
// if any of these bits are set:
if((mantissa & ((MANTISSA_FRAC_BITMAP | MANTISSA_IMPLICIT_PREFIX) >> (pointPlace - DENOM_LEN))) > 0) {
System.out.println("warning: precision of input is smaller than 1/64");
}
if(frac == 0) return String.format("%d", whole);
int denom = 64;
// test last bit, divide nom and demon by 1 if not 1
while((frac & 1) == 0) {
frac = frac >> 1;
denom = denom >> 1;
}
return String.format("%d %d/%d", whole, frac, denom);
}
(this code can probably be made shorter, but reading bit-flipping-code like this is hard enough as it is...)
I create simply Fraction library.
The library is available here: https://github.com/adamjak/Fractions
Example:
String s = "1.125";
Fraction f1 = Fraction.tryParse(s);
f1.toString(); // return 9/8
Double d = 2.58;
Fraction f2 = Fraction.createFraction(d);
f2.divide(f1).toString() // return 172/75 (2.29)
To solve this problem (in one of my projects), I took the following steps:
Built a dictionary of decimal/fraction strings.
Wrote a function to search the dictionary for the closest matching fraction depending on the "decimal" part of the number and the matching criteria.

Categories

Resources