Skip to content

Instantly share code, notes, and snippets.

@dcollien
Created December 5, 2024 11:09
Show Gist options
  • Save dcollien/6395e7f4199dafafa2ff0c6a89d7d7e3 to your computer and use it in GitHub Desktop.
Save dcollien/6395e7f4199dafafa2ff0c6a89d7d7e3 to your computer and use it in GitHub Desktop.
Decimal Expansion (JS)
function decimalExpansion(numerator, denominator) {
// Special case for 0
if (denominator === 0) {
return null;
} else if (numerator === 0) {
return { whole: 0, nonRecurring: "", recurring: null };
}
const whole = Math.floor(numerator / denominator);
let remainder = numerator % denominator;
let nonRecurring = ''; // The non-recurring part of the decimal
let recurring = null; // The recurring part of the decimal
const remainderHistory = {}; // Track positions of each remainder
// Process the decimal part
while (remainder !== 0) {
// If this remainder has been seen before, we have a repeating decimal
if (remainderHistory[remainder] !== undefined) {
recurring = nonRecurring.slice(remainderHistory[remainder]);
nonRecurring = nonRecurring.slice(0, remainderHistory[remainder]);
break;
}
// Store the position of this remainder
remainderHistory[remainder] = nonRecurring.length;
// Get the next digit in the decimal expansion
remainder *= 10;
nonRecurring += Math.floor(remainder / denominator);
remainder %= denominator;
}
return {
whole,
nonRecurring, // Non-recurring part of the decimal
recurring, // Recurring part of the decimal (or null if none)
};
}
function fractionFromDecimalExpansion({ whole, nonRecurring, recurring }) {
// Base case: if everything is zero
if (whole === 0 && nonRecurring === "" && recurring === null) {
return { numerator: 0, denominator: 1 };
}
// Parse the non-recurring part
const nonRecurringLength = nonRecurring.length;
const recurringLength = recurring ? recurring.length : 0;
// Convert whole and non-recurring part into a fraction
const wholeNumerator = whole;
const wholeDenominator = 1;
const nonRecurringNumerator = nonRecurring ? parseInt(nonRecurring, 10) : 0;
const nonRecurringDenominator = Math.pow(10, nonRecurringLength);
// If there is no recurring part
if (!recurring) {
const numerator = wholeNumerator * nonRecurringDenominator + nonRecurringNumerator;
const denominator = nonRecurringDenominator;
return simplifyFraction(numerator, denominator);
}
// Handle the recurring part
const recurringNumerator = parseInt(recurring, 10);
const recurringDenominator = Math.pow(10, recurringLength) - 1;
// Combined denominator for the recurring part
const totalRecurringDenominator = recurringDenominator * nonRecurringDenominator;
const totalRecurringNumerator =
recurringNumerator +
nonRecurringNumerator * recurringDenominator;
const totalNumerator = wholeNumerator * totalRecurringDenominator + totalRecurringNumerator;
const totalDenominator = totalRecurringDenominator;
return simplifyFraction(totalNumerator, totalDenominator);
}
// Helper function to simplify fractions
function simplifyFraction(numerator, denominator) {
const gcd = (a, b) => (b === 0 ? a : gcd(b, a % b));
const divisor = gcd(numerator, denominator);
return {
numerator: numerator / divisor,
denominator: denominator / divisor,
};
}
for (let numerator = 1; numerator < 10; numerator++) {
for (let denominator = 1; denominator < 10; denominator++) {
const expansion = decimalExpansion(numerator, denominator);
const suffix = expansion.recurring ? expansion.recurring : '';
const prefix = (expansion.nonRecurring || suffix) ? `${expansion.whole}.${expansion.nonRecurring}` : expansion.whole;
const firstLine = ' '.repeat(prefix.length) + '_'.repeat(suffix.length);
const secondLine = prefix + suffix;
const fraction = fractionFromDecimalExpansion(expansion);
console.log('------------------------------------------------------------');
console.log(`${numerator}/${denominator}`);
console.log(`${fraction.numerator}/${fraction.denominator}`);
console.log(firstLine);
console.log(secondLine);
console.log('');
console.log(JSON.stringify(expansion))
console.log('------------------------------------------------------------');
console.log('');
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment