Converting a decimal number to a fraction involves representing a number that has a fractional part (a part after the decimal point) as a ratio of two integers (a numerator and a denominator). This is a fundamental concept in mathematics, useful for simplifying expressions, performing calculations, and understanding numerical relationships.
How the Calculator Works (Exact Conversion)
The calculator first attempts an exact conversion. Any decimal can be written as a fraction by understanding place value:
The first digit after the decimal point represents tenths (1/10).
The second digit represents hundredths (1/100).
The third digit represents thousandths (1/1000), and so on.
For example, the decimal 0.75 can be written as 75/100. The calculator then simplifies this fraction to its lowest terms by dividing both the numerator and the denominator by their greatest common divisor (GCD). In the case of 75/100, the GCD is 25, so the simplified fraction is 3/4.
For terminating decimals, this method provides an exact fractional representation.
Approximate Conversion with Tolerance
Some decimals are non-terminating (like 1/3 = 0.333…). For these or for cases where you need a simpler, approximate fraction, the calculator allows for a 'tolerance'. This means it will find the 'best' fraction whose value is within a specified small range (the tolerance) of the original decimal. This is often achieved using algorithms like the continued fraction expansion.
Use Cases:
Simplifying Calculations: Working with fractions can sometimes be more precise than decimals, especially for repeating decimals.
Understanding Proportions: Fractions are intuitive for understanding parts of a whole.
Engineering and Design: Many measurements and specifications are traditionally expressed in fractions (e.g., 1/4 inch).
Education: Learning and reinforcing fundamental math concepts.
function gcd(a, b) {
var a = Math.abs(a);
var b = Math.abs(b);
while (b) {
var temp = b;
b = a % b;
a = temp;
}
return a;
}
function fractionToDecimal(numerator, denominator) {
if (denominator === 0) return NaN;
return numerator / denominator;
}
function isInteger(num) {
return Number.isInteger(num);
}
// Function to convert a decimal to a fraction using continued fractions (for approximation)
function decimalToFractionApprox(x, max_denominator) {
var n = Math.floor(x);
x -= n;
var a = [];
var h1 = 1, k1 = 0;
var h2 = 0, k2 = 1;
var delta = 1e-15; // Small epsilon for floating point comparisons
while (x > delta) {
var a_i = Math.floor(x);
a.push(a_i);
var a_n = a.length – 1;
if (a_n > 0) {
h1 = a[a_n] * h2 + h1;
k1 = a[a_n] * k2 + k1;
} else {
h1 = a[a_n];
k1 = 1;
}
if (k1 > max_denominator) {
// If exceeded max denominator, use previous best approximation
h1 = h2;
k1 = k2;
break;
}
// Update h2, k2 for next iteration
h2 = h1;
k2 = k1;
x = 1.0 / (x – a_i);
}
// If a is empty (input was an integer), return n/1
if (a.length === 0) {
return { numerator: n, denominator: 1 };
}
// Use the last valid approximation if calculation continued
if (k1 > max_denominator) {
// Fallback to previous valid calculation
a.pop(); // Remove the last a_i that caused overflow
if (a.length === 0) { // If it was the first step
return { numerator: n, denominator: 1 };
}
var last_a_i = a.pop(); // Get the last valid a_i
h1 = last_a_i * k2 + h2; // Calculate numerator using previous terms
k1 = last_a_i * k2 + k2; // Calculate denominator using previous terms
} else {
// If loop finished normally, use the final h1, k1
h1 = a[a.length -1] * h2 + h1;
k1 = a[a.length -1] * k2 + k1;
}
// Add the integer part back
return { numerator: n * k1 + h1, denominator: k1 };
}
function convertToFraction() {
var decimalInput = document.getElementById('decimalInput').value;
var toleranceInput = document.getElementById('toleranceInput').value;
var resultValueDiv = document.getElementById('result-value');
resultValueDiv.innerText = "–"; // Reset result
var decimalNum = parseFloat(decimalInput);
var tolerance = parseFloat(toleranceInput);
if (isNaN(decimalNum)) {
resultValueDiv.innerText = "Invalid decimal input";
return;
}
var resultFraction = "";
if (isNaN(tolerance) || tolerance <= 0) {
// Exact conversion for terminating decimals
var strDecimal = decimalInput.toString();
var decimalPlaces = 0;
if (strDecimal.includes('.')) {
decimalPlaces = strDecimal.split('.')[1].length;
}
if (decimalPlaces === 0) {
// It's an integer
resultFraction = decimalNum + "/1";
} else {
var denominator = Math.pow(10, decimalPlaces);
var numerator = Math.round(decimalNum * denominator);
var commonDivisor = gcd(numerator, denominator);
numerator = numerator / commonDivisor;
denominator = denominator / commonDivisor;
resultFraction = numerator + "/" + denominator;
}
} else {
// Approximate conversion using continued fractions
var maxDenominator = 10000; // Set a reasonable limit for approximation
var approxFraction = decimalToFractionApprox(decimalNum, maxDenominator);
var finalNumerator = approxFraction.numerator;
var finalDenominator = approxFraction.denominator;
// Simplify the approximated fraction again (sometimes needed)
var commonDivisor = gcd(finalNumerator, finalDenominator);
finalNumerator = finalNumerator / commonDivisor;
finalDenominator = finalDenominator / commonDivisor;
// Check if the approximation is within tolerance
var approximatedDecimal = fractionToDecimal(finalNumerator, finalDenominator);
if (Math.abs(approximatedDecimal – decimalNum) <= tolerance) {
resultFraction = finalNumerator + "/" + finalDenominator;
} else {
// If the best approximation is not within tolerance, try a simpler one or indicate failure
// For simplicity here, we'll still show the best approximation found
resultFraction = finalNumerator + "/" + finalDenominator + " (Approximate)";
}
}
resultValueDiv.innerText = resultFraction;
}