Created
December 5, 2024 11:09
-
-
Save dcollien/6395e7f4199dafafa2ff0c6a89d7d7e3 to your computer and use it in GitHub Desktop.
Decimal Expansion (JS)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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