'use strict'; // temperature-conversion.cjs -- METHOD DECK (X063), reversible temperature unit conversion. // Formulas are the exact defining relations in NIST SP 811 (2008 ed.), section 4 (Table 4, "Temperature"). function fmt(x, decimals) { return x.toLocaleString('en-US', { minimumFractionDigits: decimals, maximumFractionDigits: decimals }); } const UNITS = ['C', 'F', 'K', 'R']; // Celsius is the pivot unit for this module. function toCelsius(value, unit) { switch (unit) { case 'C': return value; case 'F': return (value - 32) * 5 / 9; case 'K': return value - 273.15; case 'R': return (value - 491.67) * 5 / 9; // R -> F: F = R - 459.67; F -> C: (F - 32) * 5/9 = (R - 491.67) * 5/9 default: throw new Error('unreachable'); } } function fromCelsius(c, unit) { switch (unit) { case 'C': return c; case 'F': return c * 9 / 5 + 32; case 'K': return c + 273.15; case 'R': return (c + 273.15) * 9 / 5; default: throw new Error('unreachable'); } } module.exports = { slug: 'temperature-conversion', title: 'Temperature conversion', deck_category: 'units', description: 'Converts a temperature between Celsius, Fahrenheit, Kelvin, and Rankine using the exact NIST SP 811 defining formulas.', inputs: [ { name: 'value', type: 'number', unit: 'from_unit', required: true, description: 'The temperature to convert' }, { 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 temperature' } ], steps: [ 'Convert the input to Celsius: C=C if from_unit is C; C=(F-32)*5/9 if F; C=K-273.15 if K; C=(R-491.67)*5/9 if R (since R=F+459.67).', 'Convert Celsius to the target unit: F=C*9/5+32; K=C+273.15; R=(C+273.15)*9/5; C=C.', 'Round the result to 2 decimal places (the conventional precision for temperature).', ], constants: [ { name: 'celsius_to_kelvin_offset', value: 273.15, unit: 'K', source: 0 }, { name: 'fahrenheit_scale_factor', value: 1.8, unit: 'F per C', source: 0 }, { name: 'fahrenheit_zero_offset', value: 32, unit: 'F', source: 0 }, { name: 'rankine_to_fahrenheit_offset', value: 459.67, unit: 'R', source: 0 }, ], sources: [ { kind: 'standard', value: 'NIST Special Publication 811 (2008 edition), section 4, Table 4 "Temperature"', title: 'Guide for the Use of the International System of Units (SI)', publisher: 'National Institute of Standards and Technology', retrieved_utc: '2026-09-30T19:29:48Z', note: 'Defining relations: t(K) = t(C) + 273.15; t(F) = (9/5) t(C) + 32; t(R) = (9/5) t(K) = t(F) + 459.67.' }, ], disclaimer: null, questionText(inputs) { return `What is ${inputs.value} degrees ${inputs.from_unit} in degrees ${inputs.to_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 (!UNITS.includes(from_unit)) throw new Error('from_unit must be one of: ' + UNITS.join(', ')); if (!UNITS.includes(to_unit)) throw new Error('to_unit must be one of: ' + UNITS.join(', ')); const c = toCelsius(value, from_unit); const result = Math.round(fromCelsius(c, to_unit) * 100) / 100; return { answer: `${fmt(result, 2)} deg ${to_unit}`, values: { result } }; }, examples: [ { name: 'worked example', inputs: { value: 100, from_unit: 'C', to_unit: 'F' }, expected: { answer: '212.00 deg F' }, check: 'By hand: F = 100 * 9/5 + 32 = 180 + 32 = 212 exactly.' }, { name: 'test vector: freezing point to Kelvin', inputs: { value: 0, from_unit: 'C', to_unit: 'K' }, expected: { answer: '273.15 deg K' }, check: 'By definition K = C + 273.15 = 0 + 273.15 = 273.15 exactly.' }, { name: 'test vector: body temperature to Celsius', inputs: { value: 98.6, from_unit: 'F', to_unit: 'C' }, expected: { answer: '37.00 deg C' }, check: 'By hand: C = (98.6 - 32) * 5/9 = 66.6 * 5/9 = 333/9 = 37 exactly.' }, ], };