Recurring fraction to decimal on BigDecimal - java

There are many ways to convert a rational number into a decimal with a recurring part (in other words, 10/3=3.(3), where (3) indicates that it repeats forever). But these only work if the numerator and denominator are integers. What can we do if the numerator or denominator is a double? For example, how can we find that
1/0.3 = 3.(3)
UPDATE:
This works but only for int numbers.
http://www.programcreek.com/2014/03/leetcode-fraction-to-recurring-decimal-java/

Let split the problem in two pieces:
Convert 1/0.3 to N/M form
Convert N/M to a.b(c) form
Lets convert 0.3 to M/N form (which give us 3/10).
String input = "123.456";
String[] parts = input.split("\\.");
String whole = parts[0];
String fraction = parts[1];
int wholeInt = Integer.parseInt(whole);
int fractionInt = Integer.parseInt(fraction);
int multiplier = pow10(fraction.length());
int n = wholeInt * multiplier + fractionInt;
int m = multiplier;
System.out.println(n + "/" + m);
I used function pow10 which simply returns 10 power input.
Now we need divide 1 by 10/3 it is easy N1/M1 divided by N2/M2 it is simply (N1*M2)/(N2*M1).
We get our result in form N/M now (we also need to normalize it by dividing both part by GCD(N, M)
Now we ready to solve main problem.
First of all get whole part
int whole = n/m;
then find fraction and repeating part
int current = n%m;
StringBuilder sb = new StringBuilder();
List<Integer> controlSet = new ArrayList<>();
while((!controlSet.contains(current))){
int currentDigit = current *10 / m;
sb.append(currentDigit);
controlSet.add(current);
current = current *10 - m * currentDigit;
}
String fraction = sb.toString().substring(0, controlSet.indexOf(current));
String repeat = sb.toString().substring(controlSet.indexOf(current));
Here we just divide in loop getting result number by number.
Main trick then number starts to repeat when we meet current that we already use.
Now you need to take all parts together. Implement GCD (lots of implementation over internet).

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"

How do I force a number with unknown digits behind the decimal mark? [duplicate]

This question already has answers here:
How to merge two int(s) into a double in JAVA?
(6 answers)
Closed 6 years ago.
Is there a way to force a number to be placed behind the decimal mark of a number?
Say I have a number = 2, and another number = 23. Is there a way for me to force 23 into 0.23, so that when I add the numbers I end up with 2.23? And is there a way to do this when the number of digits in the second number, in this case 23, are unknown?
EDIT:
I realize this was badly written. I am currently working on a program that converts from imperial units to metric units. Part of the code looks like this:
double feet = nextDouble();
double inches = nextDouble();
double heightInMeters = (feet + (inches/10)) / 3.2808;
The problem with this code is that I anticipate that the user only enters a value <0, 9> for feet. Is there a way to force the input for inches to something like 0.x where x = inches so that it doesn't matter if the number is greater than 9?
Would be lovely if it was possible without using toString() and parseInt().
You can get the number of digits in an integer, i, using:
1 + Math.floor(Math.log10(i))
(not ceil(log10(i)), since that calculates that 1 has zero digits)
You then need to divide i by 10 to the power of that number:
i / Math.pow(10, 1 + Math.floor(Math.log10(i)))
e.g.
23 / Math.pow(10, 1 + Math.floor(Math.log10(23))) == 0.23
Ideone demo
Alternatively, if you think those floating point operations log and pow are too expensive, you can determine the number of digits with a loop:
int d = 1;
while (d < i) d *= 10;
then
System.out.println(i / (double) d);
(noting that you need to cast at least one of the numerator or denominator to a floating point type, otherwise it will use integer division).
Try parsing to double like this, from a string:
Option 1
try
{
int n = 2;
int decimal = 23;
String full = Integer.toString(n) + '.' + Integer.toString(decimal);
double val = Double.parseDouble(full);
} catch (Exception e) //Or whatever exception
{
//Code
}
Option 2
Of course, there are simpler methods, like this:
try
{
int n = 2;
int decimal = 23;
double val = Double.parseDouble(n + "." + decimal);
} catch (Exception e) //Or whatever exception
{
//Code
}
I personally would recommend the solution directly above, since it is the simplest, and requires the least code.
Live Example for Second Option
Simple implementation using Strings:
public class Mainclass {
public static void main(String[] args) {
Integer num = 1546;
Integer num2 = 2;
String s = num.toString();
s = "0." + s;
Double d = Double.parseDouble(s);
System.out.println(num2+d ); // 2.1546
}
}

Converstion from int to binary

Is there a way to convert an int to binary number without using Integer.toBinaryString method?
I tried to figure out the algorithm for the conversion but haven't had any luck with it.
My task is this: (https://open.kattis.com/problems/reversebinary)
Insert an Int with help of Scanner.
Convert the Int to binary.
Reverse the binary.
Print out the new Int.
For example, the number 11 is 1011 in binary.
Now reverse the binary number 1011 and you get 1101 (which is the number 13)
and print out 13.
This is what I got, but still, I used the Integer.toBinaryString method and I get NumberFormatException.
int reverse = 0;
int number, binary;
Scanner scn = new Scanner(System.in);
number = scn.nextInt();
String b = Integer.toString(number, 2);
binary = Integer.parseInt(b);
while (binary != 0) {
reverse = reverse * 10 + binary % 10;
binary = binary / 10;
}
int newNumber = Integer.parseInt(String.valueOf(reverse), 2);
System.out.println(newNumber);
}
}
First of all, you should use the correct terms. You are not converting an int to a binary. The int type (as well as all numeric types) are already stored in a binary format. When you convert an int to a String, or a String to an int, you choose the radix that the String representation uses (such as decimal, binary, octal, hexadecimal, etc..). This determines the digits that appear in the String representation. Now, based on your example, what you wish to do is generate a number whose binary representation is the reverse of the input number. In other words, you want to reverse the bits of the input number.
Your current loop :
while (binary != 0) {
reverse = reverse * 10 + binary % 10;
binary = binary / 10;
}
calculates the decimal (radix 10) digits of binary and creates an integer whose value is the value of those digits when they are arranged in reversed order.
If you want the reverse of the binary representation of the input number, you should multiply and divide by 2 in order to obtain the binary digits (aka bits) of the input number and reverse them :
while (number != 0) {
System.out.print (number % 2); // prints a binary digit (i.e. 0 or 1)
reverse = reverse * 2 + number % 2;
number = number / 2;
}
System.out.println();
System.out.println(reverse); // prints the decimal representation of the reversed number
If number is 11, reverse will be 13, since the reverse of 1011 is 1101. This code will print both the binary representation of the reversed number (1101) and the decimal representation (13).
Instead of reversing the binary as a number, reverse it while it is still a String, new StringBuilder(b).reverse().toString(). Then convert it back to an int from base 2, and you're done.
So the entire code would be:
final Scanner scn = new Scanner(System.in);
final int number = scn.nextInt();
String b = Integer.toString(number, 2);
b = new StringBuilder(b).reverse().toString();
System.out.println(Integer.parseInt(b.toString(), 2));
Maybee the smartest solution for this problem is bit shifting. I wrote an example with a little explanation.
int number, reverse = 0;
Scanner scn = new Scanner(System.in);
number = scn.nextInt();
while (number > 0)
{
// shift all bits to the left
reverse = reverse << 1;
// extract the last bit of the number
int bit = number & 1;
// add the last bit to the reverse version
reverse |= bit;
// shift alle bits to the right
number = number >> 1;
}
System.out.println(reverse);
Integer.toBinaryString - Returns a string representation of the integer argument as an unsigned integer in base 2.
String toString(int i, int radix) -
Returns a string representation of the first argument in the radix specified by the second argument
public static void main(String[] args) {
int reverse = 0;
int number, binary;
Scanner scn = new Scanner(System.in);
number = scn.nextInt();
String b = Integer.toBinaryString(number);
binary = Integer.parseInt(b);
while (binary != 0) {
reverse = reverse * 10 + binary % 10;
binary = binary / 10;
}
int newNumber = Integer.parseInt(String.valueOf(reverse), 2);
System.out.println(newNumber);
}
Infact whatever you use cannot give an error. The above code perfectly compiles without an error.
Providing 11, gives 13 perfectly.

Java get fraction method

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/

Get first N digits of a number

I'm writing a small program that displays the factorial of a number.
When I enter the number 20 I got the number 2432902008176640000 as result.
How can I limit a decimal number in Java.
For example the number 2432902008176640000 should be 2432 (limit 4).
Thanks in advance.
The following might do what you want, if what you want to do is what I think you want to do:
long n = 2432902008176640000L; // original number
while (n > 9999) {
// while "more than 4 digits", "throw out last digit"
n = n / 10;
}
// now, n = 2432
And a demo.
Notes:
A long can only represent values as large as 9223372036854775807 (which is only about 4 times as large as the number given) before it will overflow. If dealing with larger numbers you'll need to switch to BigInteger or similar. The same technique can be used, updated for syntax differences.
As fge pointed out, this won't work as it is written over negative numbers; this can be addressed by either changing the condition (i.e. n < -9999) or first obtaining the absolute value of n (and then reverting the operation at the end).
As done in yinqiwen's answer, n > 9999 can be replaced with n >= (long)Math.pow(10, N) (preferably using a temporary variable), where N represents the number of decimal digits.
Replace N by the limit.
long v = 2432902008176640000L;
long x = (long) Math.pow(10, N);
while(v >= x)
{
v /= 10;
}
Try this, may help:
Long n = 2432902008176640000;
String num = String.valueOf(n);
num = num.subString(0, 4);
n = Long.valueOf(num);
I am assuming you mean factorial of a number.
Just convert the number into a string and use substring method to get first 4 digits only.
fact is the factorial value
String result_4_str=(fact+"").substring(0, 4);
long result_4 = Long.parseLong(result_4_str);
System.out.println(result_4);
Some of the previous answers with loops are O(n) time complexity. Here's a solution for constant time complexity:
long num = 2432902008176640000L;
int n = 4;
long first_n = (long) (num / Math.pow(10, Math.floor(Math.log10(num)) - n + 1));
You can try
long number = 2432902008176640000L ;
String numberStr = String.valueOf(number);
if(numberStr.length()>=4){
System.out.println(numberStr.substring(0, 4));
}

Categories

Resources