'use strict'; // data-size-conversion.cjs -- METHOD DECK (X063), reversible digital storage unit conversion. // Decimal prefixes (KB, MB, GB, TB) use powers of 1000; binary prefixes (KiB, MiB, GiB, TiB) use // powers of 1024, per IEC 80000-13:2008 "Quantities and units - Part 13: Information science and // technology" (the standard that defines the kibi/mebi/gibi/tebi binary prefixes). function roundSig(x, sig) { if (x === 0) return { value: 0, decimals: 0 }; const neg = x < 0; const ax = Math.abs(x); let exp = Math.floor(Math.log10(ax)); let decimals = Math.max(sig - exp - 1, 0); let factor = Math.pow(10, decimals); let value = Math.round(ax * factor) / factor; const newExp = value === 0 ? exp : Math.floor(Math.log10(value)); if (newExp !== exp) { decimals = Math.max(sig - newExp - 1, 0); factor = Math.pow(10, decimals); value = Math.round(ax * factor) / factor; } return { value: neg ? -value : value, decimals }; } function fmt(x, decimals) { return x.toLocaleString('en-US', { minimumFractionDigits: decimals, maximumFractionDigits: decimals }); } function fmtSig(x, sig) { const r = roundSig(x, sig); return fmt(r.value, r.decimals); } // Bits per 1 unit. 1 byte = 8 bits by definition; decimal prefixes are powers of 1000; // binary (IEC) prefixes are powers of 1024. const TO_BITS = { bit: 1, byte: 8, KB: 8 * Math.pow(1000, 1), MB: 8 * Math.pow(1000, 2), GB: 8 * Math.pow(1000, 3), TB: 8 * Math.pow(1000, 4), KiB: 8 * Math.pow(1024, 1), MiB: 8 * Math.pow(1024, 2), GiB: 8 * Math.pow(1024, 3), TiB: 8 * Math.pow(1024, 4), }; const UNITS = Object.keys(TO_BITS); module.exports = { slug: 'data-size-conversion', title: 'Data size conversion', deck_category: 'units', description: 'Converts a digital storage quantity between bit, byte, decimal (KB/MB/GB/TB) and binary (KiB/MiB/GiB/TiB) units per IEC 80000-13.', inputs: [ { name: 'value', type: 'number', unit: 'from_unit', required: true, description: 'The data size to convert', min: 0 }, { name: 'from_unit', type: 'string', required: true, description: 'Unit of the input value', enum: UNITS }, { name: 'to_unit', type: 'string', required: true, description: 'Unit to convert into', enum: UNITS }, ], outputs: [ { name: 'result', unit: 'to_unit', description: 'The converted data size' } ], steps: [ 'Look up the exact bit-equivalent of from_unit and of to_unit: byte=8 bits; KB/MB/GB/TB are 8*1000^n bits (decimal); KiB/MiB/GiB/TiB are 8*1024^n bits (binary).', 'Convert the input to bits: bits = value * bits_per(from_unit).', 'Convert bits to the target unit: result = bits / bits_per(to_unit).', 'Round result to 6 significant figures.', ], constants: [ { name: 'bit', value: 1, unit: 'bit', source: 0 }, { name: 'byte', value: 8, unit: 'bit', source: 0 }, { name: 'KB', value: 8000, unit: 'bit', source: 0 }, { name: 'MB', value: 8000000, unit: 'bit', source: 0 }, { name: 'GB', value: 8000000000, unit: 'bit', source: 0 }, { name: 'TB', value: 8000000000000, unit: 'bit', source: 0 }, { name: 'KiB', value: 8192, unit: 'bit', source: 0 }, { name: 'MiB', value: 8388608, unit: 'bit', source: 0 }, { name: 'GiB', value: 8589934592, unit: 'bit', source: 0 }, { name: 'TiB', value: 8796093022208, unit: 'bit', source: 0 }, ], sources: [ { kind: 'standard', value: 'IEC 80000-13:2008, Quantities and units - Part 13: Information science and technology', title: 'IEC 80000-13:2008', publisher: 'International Electrotechnical Commission', retrieved_utc: '2026-09-30T19:29:48Z', note: 'Defines the binary prefixes kibi (2^10), mebi (2^20), gibi (2^30), tebi (2^40), distinct from the SI decimal prefixes kilo/mega/giga/tera (powers of 1000) used for KB/MB/GB/TB.' }, ], disclaimer: null, questionText(inputs) { return `How many ${inputs.to_unit} are in ${inputs.value} ${inputs.from_unit}?`; }, run(inputs) { const { value, from_unit, to_unit } = inputs || {}; if (typeof value !== 'number' || !isFinite(value)) throw new Error('value must be a finite number'); if (!TO_BITS.hasOwnProperty(from_unit)) throw new Error('from_unit must be one of: ' + UNITS.join(', ')); if (!TO_BITS.hasOwnProperty(to_unit)) throw new Error('to_unit must be one of: ' + UNITS.join(', ')); const bits = value * TO_BITS[from_unit]; const result = bits / TO_BITS[to_unit]; return { answer: `${fmtSig(result, 6)} ${to_unit}`, values: { result } }; }, examples: [ { name: 'worked example', inputs: { value: 1, from_unit: 'GB', to_unit: 'GiB' }, expected: { answer: '0.931323 GiB' }, check: 'By hand: 1 GB = 8,000,000,000 bits; 1 GiB = 8,589,934,592 bits; 8,000,000,000/8,589,934,592 = 0.931322575...; rounded to 6 significant figures is 0.931323.' }, { name: 'test vector: MiB to KB', inputs: { value: 1, from_unit: 'MiB', to_unit: 'KB' }, expected: { answer: '1,048.58 KB' }, check: 'By hand: 1 MiB = 8,388,608 bits; 1 KB = 8000 bits; 8,388,608/8000 = 1048.576 exactly, rounded to 6 significant figures.' }, { name: 'test vector: byte to bit', inputs: { value: 1, from_unit: 'byte', to_unit: 'bit' }, expected: { answer: '8.00000 bit' }, check: 'By definition 1 byte = 8 bits exactly.' }, ], };