javascript
exercises
exercises.js⚡javascript
/**
* 14.1 Number Fundamentals - Exercises
*
* Practice working with JavaScript numbers, special values, and precision.
*/
/**
* Exercise 1: Safe Number Check
*
* Create a function that checks if a value is a "safe number" -
* meaning it's a finite number (not NaN, not Infinity) and within
* the safe integer range if it's an integer.
*
* @param {any} value - The value to check
* @returns {boolean} - True if the value is a safe number
*
* Requirements:
* - Return false for NaN
* - Return false for Infinity and -Infinity
* - Return false for non-number types
* - Return true for finite numbers
* - For integers, also check if they're safe integers
*/
function isSafeNumber(value) {
// Your code here
}
// console.log(isSafeNumber(42)); // true
// console.log(isSafeNumber(3.14)); // true
// console.log(isSafeNumber(NaN)); // false
// console.log(isSafeNumber(Infinity)); // false
// console.log(isSafeNumber('42')); // false
// console.log(isSafeNumber(2 ** 53)); // false (unsafe integer)
// console.log(isSafeNumber(2 ** 53 - 1)); // true (max safe integer)
/**
* Exercise 2: Parse Mixed Input
*
* Create a function that extracts a number from various input formats.
* Handle strings with units, currency, percentages, etc.
*
* @param {string} input - The input string to parse
* @returns {number} - The extracted number, or NaN if not parseable
*
* Examples:
* - "42px" → 42
* - "$1,234.56" → 1234.56
* - "50%" → 0.5
* - "1.5em" → 1.5
* - "-25.5" → -25.5
*/
function parseNumber(input) {
// Your code here
}
// console.log(parseNumber('42px')); // 42
// console.log(parseNumber('$1,234.56')); // 1234.56
// console.log(parseNumber('50%')); // 0.5
// console.log(parseNumber('1.5em')); // 1.5
// console.log(parseNumber('-25.5')); // -25.5
// console.log(parseNumber('hello')); // NaN
/**
* Exercise 3: Money Calculator
*
* Create a money calculator that handles arithmetic without
* floating-point precision errors. Work internally with cents.
*
* @param {number} amount1 - First amount in dollars
* @param {number} amount2 - Second amount in dollars
* @param {string} operation - 'add', 'subtract', 'multiply', 'divide'
* @returns {number} - Result in dollars (rounded to 2 decimal places)
*/
function moneyCalc(amount1, amount2, operation) {
// Your code here
}
// console.log(moneyCalc(0.1, 0.2, 'add')); // 0.3 (not 0.30000000000000004)
// console.log(moneyCalc(10.50, 3.25, 'subtract')); // 7.25
// console.log(moneyCalc(19.99, 3, 'multiply')); // 59.97
// console.log(moneyCalc(100, 3, 'divide')); // 33.33
/**
* Exercise 4: Number Formatter
*
* Create a function that formats numbers in different styles.
*
* @param {number} num - The number to format
* @param {string} style - 'currency', 'percent', 'compact', 'scientific'
* @param {object} options - Optional settings (locale, currency)
* @returns {string} - The formatted number
*/
function formatNumber(num, style, options = {}) {
// Your code here
}
// console.log(formatNumber(1234.56, 'currency')); // "$1,234.56"
// console.log(formatNumber(0.156, 'percent')); // "15.6%"
// console.log(formatNumber(1500000, 'compact')); // "1.5M"
// console.log(formatNumber(12345.678, 'scientific')); // "1.23e+4"
// console.log(formatNumber(1234.56, 'currency', { currency: 'EUR' })); // "€1,234.56"
/**
* Exercise 5: Base Converter
*
* Create a function that converts numbers between different bases.
*
* @param {string|number} value - The number to convert
* @param {number} fromBase - The base to convert from (2-36)
* @param {number} toBase - The base to convert to (2-36)
* @returns {string} - The number in the target base
*/
function convertBase(value, fromBase, toBase) {
// Your code here
}
// console.log(convertBase('1010', 2, 10)); // "10"
// console.log(convertBase('255', 10, 16)); // "ff"
// console.log(convertBase('ff', 16, 2)); // "11111111"
// console.log(convertBase('777', 8, 10)); // "511"
// console.log(convertBase('100', 10, 36)); // "2s"
/**
* Exercise 6: Statistics Calculator
*
* Create a function that calculates basic statistics for an array of numbers.
*
* @param {number[]} numbers - Array of numbers
* @returns {object} - Object with min, max, sum, mean, median, and range
*/
function calculateStats(numbers) {
// Your code here
}
// console.log(calculateStats([1, 2, 3, 4, 5]));
// {
// min: 1,
// max: 5,
// sum: 15,
// mean: 3,
// median: 3,
// range: 4
// }
// console.log(calculateStats([10, 20, 30, 40]));
// {
// min: 10,
// max: 40,
// sum: 100,
// mean: 25,
// median: 25,
// range: 30
// }
/**
* Exercise 7: Precision Comparator
*
* Create a function that compares two floating-point numbers
* with a specified precision level.
*
* @param {number} a - First number
* @param {number} b - Second number
* @param {number} precision - Number of decimal places to consider
* @returns {number} - -1 if a < b, 0 if equal, 1 if a > b
*/
function comparePrecision(a, b, precision = 10) {
// Your code here
}
// console.log(comparePrecision(0.1 + 0.2, 0.3, 10)); // 0 (equal)
// console.log(comparePrecision(3.14159, 3.14160, 4)); // 0 (equal at 4 decimals)
// console.log(comparePrecision(3.14159, 3.14160, 5)); // -1 (a < b)
// console.log(comparePrecision(1.0001, 1.0000, 3)); // 0 (equal at 3 decimals)
/**
* Exercise 8: BigInt Calculator
*
* Create a calculator that handles very large numbers using BigInt.
* Support basic operations and factorial calculation.
*
* @param {string} operation - 'add', 'multiply', 'power', 'factorial'
* @param {...string|number} args - Numbers as strings or numbers
* @returns {string} - Result as a string
*/
function bigCalc(operation, ...args) {
// Your code here
}
// console.log(bigCalc('add', '9007199254740991', '1000'));
// "9007199254741991"
// console.log(bigCalc('multiply', '123456789', '987654321'));
// "121932631112635269"
// console.log(bigCalc('power', '2', '100'));
// "1267650600228229401496703205376"
// console.log(bigCalc('factorial', '50'));
// "30414093201713378043612608166064768844377641568960512000000000000"
/**
* Exercise 9: Range Generator
*
* Create a function that generates an array of numbers in a range,
* with optional step and the ability to include decimal numbers.
*
* @param {number} start - Start of range (inclusive)
* @param {number} end - End of range (inclusive)
* @param {number} step - Step between numbers (default: 1)
* @returns {number[]} - Array of numbers in the range
*/
function range(start, end, step = 1) {
// Your code here
}
// console.log(range(1, 5)); // [1, 2, 3, 4, 5]
// console.log(range(0, 10, 2)); // [0, 2, 4, 6, 8, 10]
// console.log(range(5, 1, -1)); // [5, 4, 3, 2, 1]
// console.log(range(0, 1, 0.2)); // [0, 0.2, 0.4, 0.6, 0.8, 1]
// console.log(range(0.1, 0.5, 0.1)); // [0.1, 0.2, 0.3, 0.4, 0.5]
/**
* Exercise 10: Number Validator
*
* Create a comprehensive number validator that checks various conditions.
*
* @param {any} value - The value to validate
* @param {object} rules - Validation rules
* @returns {object} - { valid: boolean, errors: string[] }
*
* Rules can include:
* - type: 'integer' | 'float' | 'any'
* - min: minimum value
* - max: maximum value
* - positive: boolean
* - negative: boolean
* - multipleOf: number
*/
function validateNumber(value, rules = {}) {
// Your code here
}
// console.log(validateNumber(42, { type: 'integer', min: 0, max: 100 }));
// { valid: true, errors: [] }
// console.log(validateNumber(3.14, { type: 'integer' }));
// { valid: false, errors: ['Must be an integer'] }
// console.log(validateNumber(-5, { positive: true }));
// { valid: false, errors: ['Must be positive'] }
// console.log(validateNumber(7, { multipleOf: 3 }));
// { valid: false, errors: ['Must be a multiple of 3'] }
// console.log(validateNumber(150, { min: 0, max: 100 }));
// { valid: false, errors: ['Must be at most 100'] }
// ============================================
// SOLUTIONS
// ============================================
/*
// Solution 1
function isSafeNumber(value) {
// Must be a number type
if (typeof value !== 'number') return false;
// Must be finite (not NaN, not Infinity)
if (!Number.isFinite(value)) return false;
// If it's an integer, check if it's a safe integer
if (Number.isInteger(value)) {
return Number.isSafeInteger(value);
}
// Finite float is safe
return true;
}
// Solution 2
function parseNumber(input) {
if (typeof input !== 'string') return NaN;
// Remove currency symbols and commas
let cleaned = input.replace(/[$€£,]/g, '');
// Handle percentages
if (cleaned.endsWith('%')) {
const num = parseFloat(cleaned);
return isNaN(num) ? NaN : num / 100;
}
// Parse the number (handles units like px, em, etc.)
return parseFloat(cleaned);
}
// Solution 3
function moneyCalc(amount1, amount2, operation) {
// Convert to cents (integer arithmetic)
const cents1 = Math.round(amount1 * 100);
const cents2 = Math.round(amount2 * 100);
let result;
switch (operation) {
case 'add':
result = cents1 + cents2;
break;
case 'subtract':
result = cents1 - cents2;
break;
case 'multiply':
result = Math.round(cents1 * amount2);
break;
case 'divide':
result = Math.round(cents1 / amount2);
break;
default:
return NaN;
}
return result / 100;
}
// Solution 4
function formatNumber(num, style, options = {}) {
const locale = options.locale || 'en-US';
const currency = options.currency || 'USD';
switch (style) {
case 'currency':
return new Intl.NumberFormat(locale, {
style: 'currency',
currency: currency
}).format(num);
case 'percent':
return new Intl.NumberFormat(locale, {
style: 'percent',
minimumFractionDigits: 1,
maximumFractionDigits: 1
}).format(num);
case 'compact':
return new Intl.NumberFormat(locale, {
notation: 'compact',
maximumFractionDigits: 1
}).format(num);
case 'scientific':
return num.toExponential(2);
default:
return num.toString();
}
}
// Solution 5
function convertBase(value, fromBase, toBase) {
// Parse the input in the source base
const decimal = parseInt(String(value), fromBase);
if (isNaN(decimal)) {
return 'Invalid input';
}
// Convert to target base
return decimal.toString(toBase);
}
// Solution 6
function calculateStats(numbers) {
if (!numbers || numbers.length === 0) {
return null;
}
const sorted = [...numbers].sort((a, b) => a - b);
const sum = numbers.reduce((acc, n) => acc + n, 0);
const mean = sum / numbers.length;
// Calculate median
const mid = Math.floor(sorted.length / 2);
const median = sorted.length % 2 === 0
? (sorted[mid - 1] + sorted[mid]) / 2
: sorted[mid];
return {
min: sorted[0],
max: sorted[sorted.length - 1],
sum: sum,
mean: mean,
median: median,
range: sorted[sorted.length - 1] - sorted[0]
};
}
// Solution 7
function comparePrecision(a, b, precision = 10) {
const factor = Math.pow(10, precision);
const roundedA = Math.round(a * factor) / factor;
const roundedB = Math.round(b * factor) / factor;
if (roundedA < roundedB) return -1;
if (roundedA > roundedB) return 1;
return 0;
}
// Solution 8
function bigCalc(operation, ...args) {
switch (operation) {
case 'add':
return (BigInt(args[0]) + BigInt(args[1])).toString();
case 'multiply':
return (BigInt(args[0]) * BigInt(args[1])).toString();
case 'power':
return (BigInt(args[0]) ** BigInt(args[1])).toString();
case 'factorial':
const n = BigInt(args[0]);
let result = 1n;
for (let i = 2n; i <= n; i++) {
result *= i;
}
return result.toString();
default:
return 'Unknown operation';
}
}
// Solution 9
function range(start, end, step = 1) {
const result = [];
// Determine precision for floating-point handling
const stepDecimals = (step.toString().split('.')[1] || '').length;
const startDecimals = (start.toString().split('.')[1] || '').length;
const precision = Math.max(stepDecimals, startDecimals);
const factor = Math.pow(10, precision);
if (step > 0 && start <= end) {
for (let i = start; i <= end + Number.EPSILON; i += step) {
result.push(Math.round(i * factor) / factor);
}
} else if (step < 0 && start >= end) {
for (let i = start; i >= end - Number.EPSILON; i += step) {
result.push(Math.round(i * factor) / factor);
}
}
return result;
}
// Solution 10
function validateNumber(value, rules = {}) {
const errors = [];
// Check if it's a number
if (typeof value !== 'number' || Number.isNaN(value)) {
return { valid: false, errors: ['Must be a valid number'] };
}
// Check type
if (rules.type === 'integer' && !Number.isInteger(value)) {
errors.push('Must be an integer');
}
// Check minimum
if (rules.min !== undefined && value < rules.min) {
errors.push(`Must be at least ${rules.min}`);
}
// Check maximum
if (rules.max !== undefined && value > rules.max) {
errors.push(`Must be at most ${rules.max}`);
}
// Check positive
if (rules.positive && value <= 0) {
errors.push('Must be positive');
}
// Check negative
if (rules.negative && value >= 0) {
errors.push('Must be negative');
}
// Check multiple of
if (rules.multipleOf !== undefined) {
const remainder = Math.abs(value % rules.multipleOf);
if (remainder > Number.EPSILON && Math.abs(remainder - rules.multipleOf) > Number.EPSILON) {
errors.push(`Must be a multiple of ${rules.multipleOf}`);
}
}
return {
valid: errors.length === 0,
errors: errors
};
}
*/