Convert fraction to decimal number - java

i'm doing some exercises in my Java book. I'm very new to programming. Therefore, notice (in the code) that i'm still on Chapter one. Now I already did everything, I just want a confirmation if this is legitimate so I can feel free to move on next.
If not, I would sincerely appreciate to not do my code for me; I want advice.
Here's the question written in the book,
"Write an application that prompts/reads the numerator and denominator of a fraction as integers, then prints the decimal equivalent of the fraction."
I'll illustrate this sentence with my code:
I did a revision here. Is this one OK?..
import java.util.*;
public class ExerciseEleven {
public static void main (String[] args) {
Scanner sc = new Scanner (System.in);
double fraction;
int fractionValue;
int decimal;
double value;
System.out.println("Enter Numerator: ");
int numerator = sc.nextInt();
System.out.println("Enter Denominator: ");
int denominator = sc.nextInt();
fraction = (double) numerator / denominator;
fractionValue = (int) (fraction * 10);
decimal = fractionValue % 10;
value = decimal * 0.1;
System.out.println(value);
}
}
It compiles and works fine.
Thank you.

It doesn't do what task says it should. You read doubles instead of integers, and the decimal equivalent is not what you print out. Decimal equivalent for 1/2 is 0.5. And you print 5.
Also, you can pay attention to your code style: variable names are usually written in lowerCamelCase, like that : simpleVariable.
Update
now it prints what you need. However you do it not in the very right way and your indentation can still be improved.

It's fine (I didn't read the assignment very well, did I? Kudos to Vladimir.) ...but some comments:
Usually you want to indent methods within the class.
Standard practice is to use initial caps (Numerator) only for types (e.g., classes, interfaces, enums). Variable, field, and method names should start with a lower-case letter. Now, you're free to ignore standard practice, but if you do people will have a lot of trouble reading your code. :-)
For rounding, you probably want to look at Math.round rather than truncating with a cast. But the assignment didn't say anything about rounding.
You might want to handle the case where denominator is zero.
So keeping those in mind:
import java.util.*;
public class ExcerciseEleven {
public static void main (String[] args) {
Scanner sc = new Scanner (System.in);
System.out.println("Enter Numerator: ");
int numerator = sc.nextInt();
System.out.println("Enter Denominator: ");
int denominator = sc.nextInt();
if (denominator == 0) {
System.out.println("Can't divide by zero");
}
else {
double fraction = (double)numerator / denominator;
System.out.println(fraction);
}
}
}

Hey I am doing some thinking about this and I have noticed something interesting after looking at this source and here is the Algorithm that I plan on implementing
First I will convert the number from the Metric using the
Javax.Measure family of functions and I will get a number like
0.3750
Then I will divide the number by ONE_SIXTEENTH which = 0.0625
ONE_SIXTEENTH = 0.0625
The answer 0.3750 / ONE_SIXTEENTH = 6;
So now I know there are 6 sixteenths of the inch
Next I check to see if 6 is divisible by 4, 6/4 = 1.5 ie not a whole number so the fraction is still regarded as 6/16th of an inch for now
Next I check to see if 6 is divisible by 2, 6/2 = 3
This is a whole number so we will use it to reconstitute the fraction
So now that we have divided 6 by 2 and gotten 3 the 16 needs to be divided by 2 and we end up with 8 so 6/16th of an inch becomes 3/8th of an inch.
PS Has anyone noticed that this is similar to a fizz bang program?
____________________________________________
Here is the chart which helped me get my head around this
My workings

There are three important parts of division operation :
Sign of the result.
Integral part
Decimal part
Also, there are few corner cases where you need to deal with the fact that Integer.MIN_VALUE is greater than Integer.MAX_VALUE when compared in absolute form.
For example : -2147483648/-1 can't yield 2147483648 when divided in the form of integer types. The reason is simple. The type of the resulting type will be integer type, and the maximum positive value that a integer type variable can hold is +2147483647
To mitigate that scenario, we should at first convert both the numerator and denominator into their long positive form. That gives us the integral part of the answer.
The XOR of two numbers will have the sign bit as 1 only in case they have opposite signs. That solves the first part (sign of result) of the problem.
For decimal part, we can employ the general division rule i.e. multiply the remainder with 10 and try dividing again and repeat. Keep record of the remainder we have already come across to prevent the loop from going into unbounded iterations.
public String fractionToDecimal(int A, int B) {
StringBuilder sb = new StringBuilder((A^B) < 0 ? "-" : "");
long a = Math.abs((long)A);
long b = Math.abs((long)B);
sb.append(Long.toString(a/b));
long rem = a % b;
sb.append((rem != 0) ? "." : "");
Map<Long, Integer> remainderMap = new HashMap<>();
int pos = 0;
while (rem != 0){
sb.append(Long.toString((rem*10)/b));
remainderMap.put(rem, pos++);
rem = (rem*10) % b;
if (remainderMap.containsKey(rem)){
String currNum[] = sb.toString().split("\\.");
return currNum[0] + "." + currNum[1].substring(0, remainderMap.get(rem)) +
"(" + currNum[1].substring(remainderMap.get(rem)) + ")";
}
}
if (sb.toString().equals("-0")) return "0";
return sb.toString();
}
Sample output :
2/3 gives 0.(6)
-2147483648/-1 gives 2147483648

Related

Way to get the twos compliment decimal from binary?

I have a simple question, how do I get the twos compliment instead of the regular answer from binary? I have a program that does the booths algorithm but when it returns the decimal it gives me a number that's a bit too high, I'm doing 9 * -9 and the answer it gives is 65455. I just want to know if there is a way to get the twos compliment instead (-81). The binary I get from the code is 1111111110101111 which I know from looking around does equal -81 when finding the two's compliment, I just don't know how to get my program to recognize or say that.
Edit: I found a small fix, essentially just checking if the binary of the product equals the result I got, this is how I've been printing the binary and converting it to a decimal, putting in the print area as The answer said something had to be done here, I got it working properly but would like to clean it up if I can
public static void main(String args[]){
Scanner sc = new Scanner(System.in);
System.out.print("Enter the first number: ");
int operand1 = sc.nextInt();
System.out.print("Enter the second number: ");
int operand2 = sc.nextInt();
String answer = multiply(operand1, operand2);
System.out.println("Final Product (binary): " + answer);
int decimal=Integer.parseInt(answer,2);
if(operand1 * operand2 < 0) {
int decProduct = operand1 * operand2;
String biProduct = toBinary(decProduct, 16);
if (biProduct.length() > 16)
{
biProduct = biProduct.substring(biProduct.length() - 16);
}
if(biProduct.equals(answer)) {
decimal = decProduct;
}
}
System.out.println("Final Answer (decimal): " + decimal);
}
The computer has no idea what it means. It just has some memory and in that memory are bits. The bits that are in it, are e.g. 1111111110101111.
What does that sequence mean? Who knows. The computer doesn't know or care.
It's the print code that decides. IT decides that this is to be taken in and then rendered such that the characters -, 8, and 1 appear on your computer screen.
Thus, the error here, is in the print code. There is no converting required. The bit sequence is all the things, at once: It's 1111111110101111, it's 65455, and it is -81. Which one is shown depends on how you print it.
Given that your print code isn't in the question, you're going to have to figure it out with this information.

Calculating sin function with JAVA BigDecimal -monomial is going bigger(?)

I'm making sin function with BigDecimal in JAVA, and this is as far as I go:
package taylorSeries;
import java.math.BigDecimal;
public class Sin {
private static final int cutOff = 20;
public static void main(String[] args) {
System.out.println(getSin(new BigDecimal(3.14159265358979323846264), 100));
}
public static BigDecimal getSin(BigDecimal x, int scale) {
BigDecimal sign = new BigDecimal("-1");
BigDecimal divisor = BigDecimal.ONE;
BigDecimal i = BigDecimal.ONE;
BigDecimal num = null;
BigDecimal result = x;
//System.err.println(x);
do {
x = x.abs().multiply(x.abs()).multiply(x).multiply(sign);
i = i.add(BigDecimal.ONE);
divisor = divisor.multiply(i);
i = i.add(BigDecimal.ONE);
divisor = divisor.multiply(i);
num = x.divide(divisor, scale + cutOff, BigDecimal.ROUND_HALF_UP);
result = result.add(num);
//System.out.println("d : " + divisor);
//System.out.println(divisor.compareTo(x.abs()));
System.out.println(num.setScale(9, BigDecimal.ROUND_HALF_UP));
} while(num.abs().compareTo(new BigDecimal("0.1").pow(scale + cutOff)) > 0);
System.err.println(num);
System.err.println(new BigDecimal("0.1").pow(scale + cutOff));
return result.setScale(scale, BigDecimal.ROUND_HALF_UP);
}
}
It uses Taylor series :
picture of the fomular
The monomial x is added every iteration and always negative number.
And the problem is, absolute value of x is getting bigger and bigger, so iteration never ends.
Is there and way to find them or better way to implement it from the first place?
EDIT:
I made this code from scratch with simple interest about trigonometric functions, and now I see lots of childish mistakes.
My intention first was like this:
num is x^(2k+1) / (2k+1)!
divisor is (2k+1)!
i is 2k+1
dividend is x^(2k+1)
So I update divisor and dividend with i and compute num by sign * dividend / divisor and add it to result by result = result.add(num)
so new and good-working code is:
package taylorSeries;
import java.math.BigDecimal;
import java.math.MathContext;
public class Sin {
private static final int cutOff = 20;
private static final BigDecimal PI = Pi.getPi(100);
public static void main(String[] args) {
System.out.println(getSin(Pi.getPi(100).multiply(new BigDecimal("1.5")), 100)); // Should be -1
}
public static BigDecimal getSin(final BigDecimal x, int scale) {
if (x.compareTo(PI.multiply(new BigDecimal(2))) > 0) return getSin(x.remainder(PI.multiply(new BigDecimal(2)), new MathContext(x.precision())), scale);
if (x.compareTo(PI) > 0) return getSin(x.subtract(PI), scale).multiply(new BigDecimal("-1"));
if (x.compareTo(PI.divide(new BigDecimal(2))) > 0) return getSin(PI.subtract(x), scale);
BigDecimal sign = new BigDecimal("-1");
BigDecimal divisor = BigDecimal.ONE;
BigDecimal i = BigDecimal.ONE;
BigDecimal num = null;
BigDecimal dividend = x;
BigDecimal result = dividend;
do {
dividend = dividend.multiply(x).multiply(x).multiply(sign);
i = i.add(BigDecimal.ONE);
divisor = divisor.multiply(i);
i = i.add(BigDecimal.ONE);
divisor = divisor.multiply(i);
num = dividend.divide(divisor, scale + cutOff, BigDecimal.ROUND_HALF_UP);
result = result.add(num);
} while(num.abs().compareTo(new BigDecimal("0.1").pow(scale + cutOff)) > 0);
return result.setScale(scale, BigDecimal.ROUND_HALF_UP);
}
}
The new BigDecimal(double) constructor is not something you generally want to be using; the whole reason BigDecimal exists in the first place is that double is wonky: There are almost 2^64 unique values that a double can represent, but that's it - (almost) 2^64 distinct values, smeared out logarithmically, with about a quarter of all available numbers between 0 and 1, a quarter from 1 to infinity, and the other half the same but as negative numbers. 3.14159265358979323846264 is not one of the blessed numbers. Use the string constructor instead - just toss " symbols around it.
every loop, sign should switch, well, sign. You're not doing that.
In the first loop, you overwrite x with x = x.abs().multiply(x.abs()).multiply(x).multiply(sign);, so now the 'x' value is actually -x^3, and the original x value is gone. Next loop, you repeat this process, and thus you definitely are nowhere near the desired effect. The solution - don't overwrite x. You need x, throughout the calculation. Make it final (getSin(final BigDecimal x) to help yourself.
Make another BigDecimal value and call it accumulator or what not. It starts out as a copy of x.
Every loop, you multiply x to it twice then toggle the sign. That way, the first time in the loop the accumulator is -x^3. The second time, it is x^5. The third time it is -x^7, and so on.
There is more wrong, but at some point I'm just feeding you your homework on a golden spoon.
I strongly suggest you learn to debug. Debugging is simple! All you really do, is follow along with the computer. You calculate by hand and double check that what you get (be it the result of an expression, or whether a while loop loops or not), matches what the computer gets. Check by using a debugger, or if you don't know how to do that, learn, and if you don't want to, add a ton of System.out.println statements as debugging aids. There where your expectations mismatch what the computer is doing? You found a bug. Probably one of many.
Then consider splicing parts of your code up so you can more easily check the computer's work.
For example, here, num is supposed to reflect:
before first loop: x
first loop: x - x^3/3!
second loop: x - x^3/3! + x^5/5!
etcetera. But for debugging it'd be so much simpler if you have those parts separated out. You optimally want:
first loop: 3 separated concepts: -1, x^3, and 3!.
second loop: +1, x^5, and 5!.
That debugs so much simpler.
It also leads to cleaner code, generally, so I suggest you make these separate concepts as variables, describe them, write a loop and test that they are doing what you want (e.g. you use sysouts or a debugger to actually observe the power accumulator value hopping from x to x^3 to x^5 - this is easily checked), and finally put it all together.
This is a much better way to write code than to just 'write it all, run it, realize it doesn't work, shrug, raise an eyebrow, head over to stack overflow, and pray someone's crystal ball is having a good day and they see my question'.
The fact that the terms are all negative is not the problem (though you must make it alternate to get the correct series).
The term magnitude is x^(2k+1) / (2k+1)!. The numerator is indeed growing, but so is the denominator, and past k = x, the denominator starts to "win" and the series always converges.
Anyway, you should limit yourself to small xs, otherwise the computation will be extremely lengthy, with very large products.
For the computation of the sine, always begin by reducing the argument to the range [0,π]. Even better, if you jointly develop a cosine function, you can reduce to [0,π/2].

In Java, how to achieve this type of number rounding?

I am writing a small physics app. What I am planning to do is to make number rounding. The issue is that it is not a fixed rounding, but rather a variable rounding that depends on the value of the decimal digits. I will give an explanation for the issue.
I always need to keep the whole integer part (if any) and the first five decimal digits (if any).
half up rounding is always used.
21.1521421056 becomes 21.15214
34.1521451056 becomes 34.15215
If the result consists of only decimal digits then:
If the first five digits include non zero digits then keep them.
0.52131125 becomes 0.52131
0.21546874 becomes 0.21547
0.00120012 becomes 0.0012
If the first five digits are all zero digits 0.00000 then go down to first five digits that include non zero digits.
0.0000051234 becomes 0.0000051234
0.000000000000120006130031 becomes 0.00000000000012001
I need to play this rounding while working with BigDecimal because it is a requirement for my needs.
I think this will work, based on experimentation, if I understand correctly what you want. If d is a BigDecimal that contains the number:
BigDecimal rounded = d.round(new MathContext
(d.scale() - d.precision() < 5
? d.precision() - d.scale() + 5
: 5));
Is this, what you are looking for?
public static void main(String[] args){
double d = 0.000000000000120006130031;
System.out.println(round(d, 5));
}
private static double round(double d, int precision) {
double factor = Math.pow(10D, precision);
int value = (int)d;
double re = d-value;
if (re * factor <= 0.1 && d != 0) {
while (re * factor <= 0.1) {
factor *= 10;
}
factor *= Math.pow(10D, precision);
}
re = ((int)(re*factor))/factor+value;
return re;
}
(sorry, it's a little quick & dirty, but you can improve it, if you want)
EDIT:
make it <= in the conditions, this should work better

How do I get the quotient of two ints to round up? (5/2)

I am having some trouble with some extra credit stuff my AP Computer Science teacher assigned. Here are the instructions:
Write a WordScrambler method recombine. This method returns a String created from its two String parameters as follows:
take the first half of word1
take the second half of word2
concatenate the two halves and return the new string
For example, the following lines show some results of calling recombine. Note that if a word has an odd number of letters, the second half of the word contains the extra letter.
here are the examples it gives:
"apple" + "pear" = "apar"
"pear" + "apple" = "peple"
it then says to create method recombine below, only giving one line of code:
private String recombine(String word1, String word2)
then I have to create the rest. I made a test program just to see if my ideas were correct, that I could use length() and substring() to do it (I know I will have to use them some time in it), then I would change the code to work with the private String recombine(word1,word2) bit. So here is my test code:
public class test
{
private static String word1,word2;
public static void main(String[]args){
word1 = "apple";
word2 = "pear";
int length1 = word1.length();
int length2 = word2.length();
System.out.println(length1);
System.out.println(length2);
int half1 = (int)Math.ceil(length1 / 2);
int half2 = length2 / 2;
System.out.println(half1);
System.out.println(half2);
}
}
the output is:
5
4
2
2
As you can see, the variable half1 should be 2.5, but since you cant use half of a letter, it should round up, but even with (int)Math.ceil it still rounds down. When I take out the int, just to see if it works as a double, it gives me an error, 'Possible loss of precision, required:int; found:double;`
The general answer to your question, for the quotient of two positive numbers a and b, is to compute(*) (a + b - 1) / b with the truncating division that most programming languages have. This produces the integer immediately above the real a / b.
In your example, b is 2. The value of length1 / 2 rounded up can be computed as (length1 + 1) / 2.
(*) This is assuming that a + b - 1 can be computed without overflow, which should not be a problem in your example.
The reason your code does not round down is that the division length1 / 2 happens before Math.ceil call, and it happens in integers.
You can round up division without using Math.ceil. For that you add a number that is less than the divisor by one to the number being divided. For example, if you want to round up the result of division by ten, add nine to the dividend:
int res = (d + 9) / 10; // Rounds up
In your case, all you need is to add one to length1:
int half1 = (length1+1) / 2;
The immediate solution is just to do the division in floating point:
int half1 = (int)Math.ceil(length1 / 2.0);
2 is an int literal and 2.0 is a double literal. Java will automatically promote length1 to double in the presence of 2.0 so this is effectively the following:
int half1 = (int)Math.ceil((double)length1 / 2.0);
But as noted by the other two answers, you don't need to use floating point. Furthermore, double only has 53 bits of integral precision so while doing the division in floating point works for an int it may result in error for a long.

How can I turn a floating point number into the closest fraction represented by a byte numerator and denominator?

How can I write an algorithm that given a floating point number, and attempts to represent is as accurately as possible using a numerator and a denominator, both restricted to the range of a Java byte?
The reason for this is that an I2C device wants a numerator and denominator, while it would make sense to give it a float.
For example, 3.1415926535... would result in 245/78, rather than 314/100 or 22/7.
In terms of efficiency, this would be called around three times at the start of the program, but after that not at all. So a slow algorithm isn't too bad.
Here's the code I used in the end (based on uckelman's code)
public static int[] GetFraction(double input)
{
int p0 = 1;
int q0 = 0;
int p1 = (int) Math.floor(input);
int q1 = 1;
int p2;
int q2;
double r = input - p1;
double next_cf;
while(true)
{
r = 1.0 / r;
next_cf = Math.floor(r);
p2 = (int) (next_cf * p1 + p0);
q2 = (int) (next_cf * q1 + q0);
// Limit the numerator and denominator to be 256 or less
if(p2 > 256 || q2 > 256)
break;
// remember the last two fractions
p0 = p1;
p1 = p2;
q0 = q1;
q1 = q2;
r -= next_cf;
}
input = (double) p1 / q1;
// hard upper and lower bounds for ratio
if(input > 256.0)
{
p1 = 256;
q1 = 1;
}
else if(input < 1.0 / 256.0)
{
p1 = 1;
q1 = 256;
}
return new int[] {p1, q1};
}
Thanks for those who helped
I've written some code (in Java, even) to do just the thing you're asking for. In my case, I needed to display a scaling factor as both a percentage and a ratio. The most familiar example of this is the zoom dialog you see in image editors, such as the GIMP.
You can find my code here, in the updateRatio() method starting at line 1161. You can simply use it, so long as the LGPL license works for you. What I did essentially follows what's done in the GIMP---this is one of those things where there's pretty much only one efficient, sensible way to do it.
How worried are you about efficiency? If you're not calling this conversion function 100s of times per second or more, then it probably wouldn't be all that hard to brute-force through every possible denominator (most likely only 255 of them) and find which one gives the closest approximation (computing the numerator to go with the denominator is constant time).
I would comment, but I don't have rep yet...
Eric's answer above doesn't consider the case where an exact result is possible. For example, if you use 0.4 as input, then the representation should be 2/5, in which case you end up with a division by zero in the third iteration of the loop (r=0 on second loop => r = 1/r error on third).
So you want to modify the while loop to exclude that option:
while(true)
should be
while(r != 0)
You should look at the Farey Sequence.
Given a limit on the denominator d, the Farey Sequence is every fraction having denominator <= d.
Then, you would simply take your float and compare it to the resolved value of the Farey fraction. This will allow you to represent your float in terms of repeating-decimal reals.
Here is a page on its implementation in java:
http://www.merriampark.com/fractions.htm
Here is a good demonstration of their use:
http://www.maths.surrey.ac.uk/hosted-sites/R.Knott/Fractions/fareySB.html
What about using Apache's BigFraction:
import org.apache.commons.math3.fraction.BigFraction;
public static BigFraction GetBigFraction(double input)
{
int precision = 1000000000;
return new BigFraction((int)(input * (double)precision), precision);
}
I reached out here out of curiosity, but I remembered there's such feature in Python standard library fractions.
Maybe, we can look into the source code of the two functions:
Fraction.from_float
Fraction.limit_denominator

Categories

Resources