Fraction to Recurring Decimal - java

Working on this problem, and also did a few reference to similar solutions. One thing I am confuse is, why we break the loop as long as there is one repetitive number? Is it possible the number repeat for 2-3 times and then changed to another different number? Thanks.
I mean this part specifically,
if (map.containsKey(num)) {
int index = map.get(num);
res.insert(index, "(");
res.append(")");
break;
}
The problem,
Given two integers representing the numerator and denominator of a fraction, return the fraction in string format.
If the fractional part is repeating, enclose the repeating part in parentheses.
For example,
Given numerator = 1, denominator = 2, return "0.5".
Given numerator = 2, denominator = 1, return "2".
Given numerator = 2, denominator = 3, return "0.(6)".
public class Solution {
public String fractionToDecimal(int numerator, int denominator) {
if (numerator == 0) {
return "0";
}
StringBuilder res = new StringBuilder();
// "+" or "-"
res.append(((numerator > 0) ^ (denominator > 0)) ? "-" : "");
long num = Math.abs((long)numerator);
long den = Math.abs((long)denominator);
// integral part
res.append(num / den);
num %= den;
if (num == 0) {
return res.toString();
}
// fractional part
res.append(".");
HashMap<Long, Integer> map = new HashMap<Long, Integer>();
map.put(num, res.length());
while (num != 0) {
num *= 10;
res.append(num / den);
num %= den;
if (map.containsKey(num)) {
int index = map.get(num);
res.insert(index, "(");
res.append(")");
break;
}
else {
map.put(num, res.length());
}
}
return res.toString();
}
}
thanks in advance,
Lin

The code doesn't stop when it sees a digit repeated. It stops when it notes that it has reached a state which it was already in. If it reaches the same state again, it means that we are about to repeat a division that we have already done, which means that the dividend and remainder are going to be the same, and we are going to do the same series of steps we have already done.
When that happens, it means a repetition, and it stops and adds the parentheses.
For example, let's divide 123 by 999. This should give us the repeating decimal 0.123123123..., so the output should be 0.(123).
123 / 999 is 0. The remainder is 123. We start with 0.
Multiply the remainder by 10. Now we have 1230 / 999. Dividend is 1, remainder is 231. Now we have 0.1
Multiply the remainder by 10. Now we have 2310 / 999. Dividend is 2, remainder is 312. Now we have 0.12
Multiply the remainder by 10. Now we have 3120 / 999. Dividend is 3, remainder is 123. Now we have 0.123
Multiply the remainder by 10. Now we have 1230 / 999... wait, we have already done that! That means that as we continue to divide, we'll get to that number again and again. Stop and put parentheses around the repeating part.
The map is there to tell us which numbers we have already divided, and at which index in the StringBuilder. When we find a number we have already divided, we use that index to know where to insert the parenthesis.

Clearly it's possible to have a decimal number with two or more decimals recurring and then a different decimal. For example 449/1000 = 0.449

Here is my solution in Java to this problem:
/**
* Given two integers a and b, return the result as a String.
* Display the repeating part of the fraction in parenthesis.
*
* Runs in O(b)
*
* #author Raed Shomali
*/
public class Divider {
private static final String DOT = ".";
private static final String ERROR = "ERROR";
private static final String LEFT_PARENTHESIS = "(";
private static final String RIGHT_PARENTHESIS = ")";
public static String divide(final int a, final int b){
if (b == 0) {
return ERROR;
}
int value = a / b;
int remainder = a % b;
return String.valueOf(value) + DOT + divider(remainder, b);
}
private static String divider(final int a, final int b) {
final Map<Integer, Integer> remainderIndexMap = new HashMap<>();
final List<Integer> values = new ArrayList<>();
int value;
int remainder = a;
while (!remainderIndexMap.containsKey(remainder)) {
remainderIndexMap.put(remainder, values.size());
remainder *= 10;
value = remainder / b;
remainder = remainder % b;
values.add(value);
}
final int index = remainderIndexMap.get(remainder);
final StringBuilder result = new StringBuilder();
for (int i = 0; i < index; i++) {
result.append(values.get(i));
}
result.append(LEFT_PARENTHESIS);
for (int i = index; i < values.size(); i++) {
result.append(values.get(i));
}
result.append(RIGHT_PARENTHESIS);
return result.toString();
}
}
Basically, the idea is simple. Using the same long division technique, you know when to stop when you have already seen the same remainder value.
Here are some test cases to show a few different scenarios:
divide(0, 0) // "ERROR"
divide(1, 2) // "0.5(0)"
divide(0, 3) // "0.(0)"
divide(10, 3) // "3.(3)"
divide(22, 7) // "3.(142857)"
divide(100, 145) // "0.(6896551724137931034482758620)"
If you are interested in a solution written in Go, you can find it here https://github.com/shomali11/util

This problem is actually very simple to solve if we use the long division technique that we learnt in 4th grade.
Suppose you need to divide 92 by 22. How do you do it using the long division method. How do you detect a repeating pattern?
Simple, you know you have a repeating pattern of decimals when you encounter a previously encountered reminder. You'll need to store the reminders and the corresponding index of the result in a dictionary and using the same you could detect/print repeating decimals. Working python code below.
def divide(numerator, denominator):
sign, res, lead = '', '', ''
if (numerator < 0) ^ (denominator < 0) and numerator != 0:
sign = '-'
numerator = abs(numerator)
denominator = abs(denominator)
remainders = defaultdict(list)
if numerator < denominator:
lead = '0'
_x = str(numerator)
r = 0
i = 0
j = 0
while True:
if i < len(_x):
d = int(str(r)+_x[i])
q = d // denominator
if not (q == 0 and len(res) == 0):
res += str(q)
r = d - (q * denominator)
i += 1
elif i >= len(_x) and j <= 9223372036854775807:
if r == 0:
return sign+lead+res
if j == 0:
remainders[r] = [True, len(res)+1]
res += '.'
d = int(str(r) + '0')
q = d // denominator
res += str(q)
r = d - (q * denominator)
if remainders[r] and remainders[r][0]:
res = res[0:remainders[r][1]] + '(' + res[remainders[r][1]:] + ')'
return sign+lead+res
remainders[r] = [True, len(res)]
j += 1
else:
return sign+lead+res

Related

How do you add digits to the front of a number?

How would you add digits to the beginning of a number (left hand side) without using a string?
I know that if you try this:
(Some psuedo code)
Let's say I try to make number 534
int current = 5;
int num = 0;
num = (num*10) +current;
then
int current = 3;
int num = 5
num = (num*10) + current;
would make: 53
then
int current = 4;
int num = 53;
num = (num*10) + current;
would make 534
It would keep adding numbers to the right hand side of the number.
However, I am a bit confused on how you would do the opposite. How would you add numbers on the left, so instead of 534 it makes 435?
int num = 123;
int digits = 456;
int powerOfTen = (int) Math.pow(10, (int) (Math.log10(digits) + 1));
int finalNum = digits * powerOfTen + num;
System.out.println(finalNum); // Output: 456123
The number of digits in digits is calculated using Math.log10 and Math.pow, and then used to determine the appropriate power of 10 to multiply digits by. The result is then added to num to obtain the final number with the added digits.
Multiply the digit to add by increasing powers of 10 before summing with the current number.
int num = 0, pow = 1;
num += 5 * pow;
pow *= 10;
num += 3 * pow;
pow *= 10;
num += 4 * pow; // num = 435 at this point
pow *= 10;
// ...
An example without the use of libraries could be this:
First, get the number of digits. Then calculate the number you have to add to your initial number. The sum of these two numbers is the result you're after.
private int addNumberInFrontOf(int initialNumber, int initialNumberToAdd){
int numberOfDigits = getDigits(initialNumber);
int getActualNumberToAdd = getNumberToAdd(initialNumberToAdd, numberOfDigits);
return initialNumber + getActualNumberToAdd;
}
To calculate the number of digits, you can count the number of times you can divide the initial number by 10. Notice you need to use a do-while loop because otherwise the loop wouldn't be triggered if your initial number was 0.
private int getDigits(int number) {
int count = 0;
do {
number = number / 10;
count += 1;
} while (number != 0);
return count;
}
Calculate the number you need to add to your initial number by multiplying the initial number to add with the magnitude. The magnitude simply is 1 multiplied with 10 for every digit in the initial number.
private int getNumberToAdd(int number, int numberOfDigits) {
int magnitude = 1;
for (int i = 0; i < numberOfDigits; i++) {
magnitude *= 10;
}
return number * magnitude;
}
For example, addNumberInFrontOf(456, 123) would result in 123456. Of course, this method won't work when you use positive and negative numbers combined.
You can use String for example.
public static int addLeft(int cur, int num) {
return num == 0 ? cur : Integer.parseInt(cur + String.valueOf(num));
}
In case you want to avoid working with String, you can use recursion instead.
public static int addLeft(int cur, int num) {
return num == 0 ? cur : addLeft(cur, num / 10) * 10 + num % 10;
}
You can use some math, in python
import math
def addLeft(digit, num):
return digit * 10 ** int(math.log10(num) + 1) + num
Note that this might fail for very large numbers on account of precision issues
>>> addLeft(2, 100)
2100
>>> addLeft(3, 99)
399
>>> addLeft(6, 99999999999999)
699999999999999
>>> addLeft(5, 999999999999999)
50999999999999999 (oops)

Is there a faster way to convert a hexadecimal fractional part to a decimal one?

I wrote a program that generates digits of pi in hexadecimal. Every so often, at benchmark values, I would like to convert the hexadecimal value I have into a decimal one and save it to a file. Currently I am using BigDecimal to do that math with this code:
private static String toDecimal(String hex) {
String rawHex = hex.replace(".", "");
BigDecimal base = new BigDecimal(new BigInteger(rawHex, 16));
BigDecimal factor = new BigDecimal(BigInteger.valueOf(16).pow(rawHex.length() - 1));
BigDecimal value = base.divide(factor);
return value.toPlainString().substring(0, hex.length());
}
Note that this method will only work for hexadecimal values with one digit in the integral part, pi included, do not copy and paste this for general use.
So this code works fine, but for the latest benchmark, 2.5m digits, the conversion took 11.3 hours to complete.
Is there any faster way to do this manually?
I tried dividing the first decimal place by 16, the second by 16^2, etc but this would quickly get out of hand. Maybe some way of bitshifting the digits back to keep the divisor low? But potentially the n+1, n+2, n+3, etc digits need to be processed to get the correct value for n.
First, I believe your function toDecimal is wrong as it doesn't correctly convert input ".1a" (it's off by a factor of 16), for example, and throws an exception for input ".800". The third line should be:
BigDecimal factor = new BigDecimal(BigInteger.valueOf(16).pow(rawHex.length()));
The exception arises from:
return value.toPlainString().substring(0, hex.length());
The converted value could be shorter than the input value and you get a java.lang.StringIndexOutOfBoundsException.
Moving on:
In truth I have not benchmarked this against your current method; I just offer this as "food for thought." Here I am doing the multiplications as a child is taught to do it in school and in your case we have a large loop just to produce one digit. But if you could somehow adapt this to use BigDecimal (it's not clear how you would) it might be quicker than your current approach (what's really needed is a BigHexadecimal class).
It can be observed that converting a fraction from one base to another can be done using multiplications. In this case we have the following hexadecimal fraction (we can ignore the integer portion, which is 3 when converting pi):
.h1h2h3h4 ... hn
where hn is the nth hexadecimal "nibble".
We wish to convert the above to the following decimal fraction:
.d1d2d3d4 ... dn
where dn is the nth decimal digit.
If we were to multiply both quantities by 10, we would get:
h'1.h'2h'3h'4 ... h'n
The primes (`) denote that we have completely new hexadecimal nibble values following the multiplication.
and
d1.d2d3d4 ... dn
The multiplication by 10 just shifts the decimal fraction one place to the left.
We must note that the quantities to the left of the decimal point must be equal, i.e. d1 == h'1. Thus we repeatedly multiply our hexadecimal fraction by 10 and each time we do we take the integer portion as the next decimal digit for our conversion. We repeat this until either our new hexadecimal fraction becomes 0 or some arbitrary number of decimal digits have been produced:
See Java Demo
class Test {
private static String toDecimal(String hex, int numberDigits) {
/* converts a string such as "13.1a" in base 16 to "19.1015625" in base 10 */
int index = hex.indexOf('.');
assert index != -1;
StringBuilder decimal = new StringBuilder((index == 0) ? "" : String.valueOf(Integer.parseInt(hex.substring(0, index), 16)));
decimal.append('.');
int l = hex.length() - index - 1;
assert l >= 1;
int firstIndex = index + 1;
int hexDigits[] = new int[l];
for (int i = 0; i < l; i++) {
hexDigits[i] = Integer.parseInt(hex.substring(i + firstIndex, i + firstIndex + 1), 16);
}
while (numberDigits != 0 && l != 0) {
int carry = 0;
boolean allZeroes = true;
for (int i = l - 1; i >= 0; i--) {
int value = hexDigits[i] * 10 + carry;
if (value == 0 && allZeroes) {
l = i;
}
else {
allZeroes = false;
carry = (int)(value / 16);
hexDigits[i] = value % 16;
}
}
numberDigits--;
if (carry != 0 || (numberDigits != 0 && l != 0))
decimal.append("0123456789".charAt(carry));
}
return decimal.toString();
}
public static void main(String[] args) {
System.out.println(toDecimal("13.1a", 15));
System.out.println(toDecimal("13.8", 15));
System.out.println(toDecimal("13.1234", 15));
}
}
Prints:
19.1015625
19.5
19.07110595703125
Thank you to #Booboo for the solution to this problem. I improved on his code a little so it should work in every case. I wanted to post it here for future visitors.
/**
* Converts a hex number string to a decimal number string.
*
* #param hex The hex number string.
* #param accuracy The number of decimal places to return in the decimal number string.
* #return The decimal number string.
*/
public static String hexToDecimal(String hex, int accuracy) {
if (!hex.matches("[0-9A-Fa-f.\\-]+") || (accuracy < 0)) {
return "";
}
boolean negative = hex.startsWith("-");
hex = hex.replaceAll("^-", "");
String integral = hex.contains(".") ? hex.substring(0, hex.indexOf(".")) : hex;
String fraction = hex.contains(".") ? hex.substring(hex.indexOf(".") + 1) : "";
if (integral.contains("-") || fraction.contains(".") || fraction.contains("-")) {
return "";
}
StringBuilder decimal = new StringBuilder();
decimal.append(negative ? "-" : "");
decimal.append(integral.isEmpty() ? "0" : new BigDecimal(new BigInteger(integral, 16)).toPlainString());
if (fraction.isEmpty() || (accuracy == 0)) {
return decimal.toString();
}
decimal.append(".");
int numberDigits = accuracy;
int length = Math.min(fraction.length(), numberDigits);
int[] hexDigits = new int[numberDigits];
Arrays.fill(hexDigits, 0);
IntStream.range(0, length).boxed().parallel().forEach(i -> hexDigits[i] = Integer.parseInt(String.valueOf(fraction.charAt(i)), 16));
while ((numberDigits != 0)) {
int carry = 0;
for (int i = length - 1; i >= 0; i--) {
int value = hexDigits[i] * 10 + carry;
carry = value / 16;
hexDigits[i] = value % 16;
}
decimal.append(carry);
numberDigits--;
}
return decimal.toString();
}
/**
* Converts a hex number string to a decimal number string.
*
* #param hex The hex number string.
* #return The decimal number string.
* #see #hexToDecimal(String, int)
*/
public static String hexToDecimal(String hex) {
String fraction = hex.contains(".") ? hex.substring(hex.indexOf(".") + 1) : "";
return hexToDecimal(hex, fraction.length());
}
public static void main(String[] args) {
//integer
Assert.assertEquals("0", hexToDecimal("0"));
Assert.assertEquals("1", hexToDecimal("1"));
Assert.assertEquals("9", hexToDecimal("9"));
Assert.assertEquals("15", hexToDecimal("F"));
Assert.assertEquals("242", hexToDecimal("F2"));
Assert.assertEquals("33190", hexToDecimal("81A6"));
Assert.assertEquals("256", hexToDecimal("100"));
Assert.assertEquals("1048576", hexToDecimal("100000"));
Assert.assertEquals("5191557193152165532727847676938654", hexToDecimal("FFF6AA0322BC458D5D11A632099E"));
Assert.assertEquals("282886881332428154466487121231991859970997056152877088222", hexToDecimal("B897A12C89896321C454A7DD9E150233CBB87A9F0233DDE"));
Assert.assertEquals("-256", hexToDecimal("-100"));
Assert.assertEquals("-144147542", hexToDecimal("-8978456"));
Assert.assertEquals("-332651442596728389665499138728075237402", hexToDecimal("-FA42566214321CC67445D58EE874981A"));
Assert.assertEquals("33190", hexToDecimal("81a6"));
//decimal
Assert.assertEquals("0.10", hexToDecimal("0.1a"));
Assert.assertEquals("0.5", hexToDecimal("0.8"));
Assert.assertEquals("0.0711", hexToDecimal("0.1234"));
Assert.assertEquals("0.528966901", hexToDecimal("0.876A5FF4A"));
Assert.assertEquals("-0.528966901", hexToDecimal("-0.876A5FF4A"));
Assert.assertEquals("-0.00000000", hexToDecimal("-0.00000001"));
Assert.assertEquals("-0.62067648792835838863907521427468", hexToDecimal("-0.9EE4A7810C666FF7453D06A44621030E"));
Assert.assertEquals("0.528966901", hexToDecimal("0.876a5ff4a"));
Assert.assertEquals("0.528966901", hexToDecimal(".876a5ff4a"));
Assert.assertEquals("-0.528966901", hexToDecimal("-.876a5ff4a"));
//combined
Assert.assertEquals("15.33693", hexToDecimal("F.56412"));
Assert.assertEquals("17220744.33934412", hexToDecimal("106C488.56DF41A2"));
Assert.assertEquals("282886881332428154466487121231991859970997056152877088222.62067648792835838863907521427468", hexToDecimal("B897A12C89896321C454A7DD9E150233CBB87A9F0233DDE.9EE4A7810C666FF7453D06A44621030E"));
Assert.assertEquals("-17220744.33934412", hexToDecimal("-106C488.56DF41A2"));
Assert.assertEquals("-282886881332428154466487121231991859970997056152877088222.62067648792835838863907521427468", hexToDecimal("-B897A12C89896321C454A7DD9E150233CBB87A9F0233DDE.9EE4A7810C666FF7453D06A44621030E"));
Assert.assertEquals("-17220744.33934412", hexToDecimal("-106c488.56df41a2"));
Assert.assertEquals("3.14159265358979323846264338327950288419716939937510582097494459230781640628620899862803482534211706798214808", hexToDecimal("3.243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89452821E638D01377BE5466CF34E90C6CC0AC29B7C97"));
//accuracy
Assert.assertEquals("-0.00000", hexToDecimal("-0.00000001", 5));
Assert.assertEquals("-0.000000000232830", hexToDecimal("-0.00000001", 15));
Assert.assertEquals("-0", hexToDecimal("-0.00000001", 0));
Assert.assertEquals("282886881332428154466487121231991859970997056152877088222.5", hexToDecimal("B897A12C89896321C454A7DD9E150233CBB87A9F0233DDE.9EE4A7810C666FF7453D06A44621030E", 1));
Assert.assertEquals("3.14", hexToDecimal("3.243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89452821E638D01377BE5466CF34E90C6CC0AC29B7C97", 2));
Assert.assertEquals("3.1415926535", hexToDecimal("3.243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89452821E638D01377BE5466CF34E90C6CC0AC29B7C97", 10));
Assert.assertEquals("3.1415926535897932384626433", hexToDecimal("3.243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89452821E638D01377BE5466CF34E90C6CC0AC29B7C97", 25));
//invalid
Assert.assertEquals("", hexToDecimal("0.00000.001"));
Assert.assertEquals("", hexToDecimal("0.00000-001"));
Assert.assertEquals("", hexToDecimal("156-081.00000001"));
Assert.assertEquals("", hexToDecimal("hello"));
Assert.assertEquals("", hexToDecimal("9g"));
Assert.assertEquals("", hexToDecimal("9G"));
Assert.assertEquals("", hexToDecimal("546.FDA", -1));
Assert.assertEquals("", hexToDecimal("546.FDA", -999));
}

How to round a double to n length (not n decimal places)? [duplicate]

This question already has answers here:
How to round a number to n decimal places in Java
(39 answers)
Closed 6 years ago.
I have been trying to find a way to make sure the length of the double "value" is not larger than 10. However, this is becoming difficult to program since I am not rounding it to a certain number of decimal places.
For example, 1234567.8912 and 12.345678912 are both larger than 10 digits however, they will have to be rounded to a different number of decimal places. My logic was to find where the decimal point occurs and rounding the double to "10 - number of digits before the decimal place".
I created two different methods and both methods won't seem to work correctly.
if ((Double.toString(value)).length()> 10){
int counter = 0;
double no_of_dec = 1;
double no_of_int = 1;
double new_value = 0;
for (int i = 0; i< (Double.toString(value)).length(); i++){
if ( (Character.toString((Double.toString(value)).charAt(i))).equals(".") ){
counter = 1;
} if (counter == 1){
no_of_dec = no_of_dec * 10;
} else if (counter == 0){
no_of_int = no_of_int * 10;
}
}
no_of_dec = no_of_dec / (no_of_int);
new_value = (double)Math.round(value * 100d/100d);
return Double.toString(new_value);
} else {
return Double.toString(value);
}
if ((Double.toString(value)).length()> 10){
double no_of_dec = 0;
double no_of_int = 0;
double new_value = 0;
for (int i = 0; i< (Double.toString(value)).length(); i++){
while (!(Character.toString((Double.toString(value)).charAt(i))).equals(".")){
no_of_int = no_of_int + 1;
}
}
no_of_dec = (Double.toString(value)).length() - no_of_int;
no_of_dec = no_of_dec * 10;
new_value = (double)Math.round(value * no_of_dec/no_of_dec);
return Double.toString(new_value);
} else {
return Double.toString(value);
}
}
I did it this way:
private static BigDecimal getRounded(double n, int totalDigits) {
String nString = Double.toString(n); // transform to string to make the job easier
if(nString.contains(".")) {
int dotPos = nString.indexOf("."); // = number of digits before the decimal point
int remainingDigits = totalDigits - dotPos; // = remaining digits after the decimal point
return new BigDecimal(nString).setScale(remainingDigits, BigDecimal.ROUND_HALF_UP); // round
}
return new BigDecimal(n);
}
This was my test:
double n = 1234567.8912;
System.out.println(getRounded(n, 10));
n = 12.345678915;
System.out.println(getRounded(n, 10));
And this the result:
1234567.891
12.34567892
Demo: http://ideone.com/my7eB2
BigDecimal has an operation for doing this:
double truncate(double value) {
BigDecimal b = new BigDecimal(String.valueOf(value));
b = b.round(new MathContext(10));
return b.doubleValue();
}
There is a reason for using the BigDecimal(String) constructor and not the BigDecimal(double) constructor. doubles and floats are not base 10 numbers, so they don’t exactly represent the values we see when we print them; the constructor documentation has a good illustration of this. This is not unique to Java and is true in most languages.
Update:
4castle points out that the above won’t work for nonzero numbers with a magnitude less than 1, since BigDecimal doesn’t consider the zero integer part a significant digit. You can work around that:
double truncate(double value) {
int precision = 10;
if (value != 0 && Math.abs(value) < 1) {
precision--;
}
BigDecimal b = new BigDecimal(String.valueOf(value));
b = b.round(new MathContext(precision));
return b.doubleValue();
}
Update 2:
BackSlash points out that it’s more complex than the above for nonzero numbers between -1 and 1. I’m sure it’s possible to calculate the exact precision needed, but I think it’s simpler to just eliminate the issue by adding 1 for rounding purposes:
double truncate(double value) {
BigDecimal b = new BigDecimal(String.valueOf(value));
MathContext context = new MathContext(10);
if (value > 0 && value < 1) {
b = b.add(BigDecimal.ONE);
b = b.round(context);
b = b.subtract(BigDecimal.ONE);
} else if (value < 0 && value > -1) {
b = b.subtract(BigDecimal.ONE);
b = b.round(context);
b = b.add(BigDecimal.ONE);
} else {
b = b.round(context);
}
return b.doubleValue();
}

The method returns true if the integer is divisible by 3 and returns false if the integer is not divisible by 3

This is what I have so far; I have to use this main method.
public class HW4 {
public static boolean isDivisibleByThree(String n) {
int sum = 0;
int value;
for (int k = 0; k < n.length(); k++) {
char ch = n.charAt(k);
value = Character.getNumericValue(ch);
sum = sum*value;
}
return sum*3 == 0;
}
}
It always comes out true and I'm really stuck in this part. So if you can, can you help me out?
A sum is a cumulative addition (not multiplication).
Change this line:
sum = sum * value;
To
sum = sum + value;
Or the more brief version:
sum += value;
Much easier solution: use the mod-function:
int number = int.Parse(input);
bool result = (number % 3 == 0);
Two things:
sum = sum * value? This should probably be sum = sum + value, or short sum += value
sum * 3 == 0 should probably be sum % 3 == 0
If you are required to not use the % operator, you could alternatively do:
double check = (double)sum / 3.0;
return check == (int)check;
The problem with negative numbers is that the - gets parsed too, you could sove it by dropping it:
if (n[0] == '-') {
n = n.substring(1);
}
This drops the sign if it is negative and does nothing otherwise.
Unless I'm missing something, you would first use Integer.parseInt(String) to parse the int from the String. Then you can divide that value by 3 using integer division. Finally, test if that number multiplied by 3 is the original value.
int value = Integer.parseInt(n);
int third = value / 3;
return (value == third * 3);

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