Updated in 2025 for correctness.
So it appears that this is a non-trivial operation if you absolutely need correctness and support all kinds of inputs, including scientific notations. Due to the limitations of the floating number representations in the JavaScript engines, you have to do some complex computations and possibly use some external libraries like Decimal.js.
Here is the fastest function that I could get, that supports scientific notation and invalid number inputs. Keep in mind that this still has some issues for specific use cases like when you pass 1.0000000000000001, JavaScript will already simplify it as 1 before the function is executed. But overall it is the most correct and versatile function I could come with.
import Decimal from 'decimal.js';
/**
* Extracts the decimal portion of a number or base-10 string.
* Fast path for normal floats. Uses decimal.js only when needed.
*
* @param {number|string} input - The input value
* @param {boolean} [preserveSign=false] - Whether to preserve the decimal's sign
* @returns {number} The decimal portion
*/
function getDecimalPart(input, preserveSign = false) {
if (typeof input === 'number') {
if (!Number.isFinite(input)) return 0;
const str = input + ''; // fast coercion
const eIndex = str.indexOf('e');
const dotIndex = str.indexOf('.');
if (eIndex === -1 && dotIndex !== -1) {
// fast float path
const fracStart = dotIndex + 1;
const len = str.length - fracStart;
if (len === 0) return 0;
let dec = 0;
let factor = 0.1;
for (let i = fracStart; i < str.length; i++) {
const code = str.charCodeAt(i);
if (code >= 48 && code <= 57) { // '0'..'9'
dec += (code - 48) * factor;
factor *= 0.1;
} else {
const d = new Decimal(str);
const int = d.trunc();
let frac = d.minus(int);
if (!preserveSign) frac = frac.abs();
return frac.toNumber();
}
}
return preserveSign && input < 0 ? -dec : dec;
}
// fallback: scientific notation or unprintable fraction
const d = new Decimal(str);
const int = d.trunc();
let frac = d.minus(int);
if (!preserveSign) frac = frac.abs();
return frac.toNumber();
}
if (typeof input === 'string') {
const eIndex = input.indexOf('e');
const dotIndex = input.indexOf('.');
if (eIndex === -1 && dotIndex !== -1) {
const fracStart = dotIndex + 1;
const len = input.length - fracStart;
if (len === 0) return 0;
let dec = 0;
let factor = 0.1;
const isNegative = input[0] === '-';
for (let i = fracStart; i < input.length; i++) {
const code = input.charCodeAt(i);
if (code >= 48 && code <= 57) {
dec += (code - 48) * factor;
factor *= 0.1;
} else {
const d = new Decimal(input);
const int = d.trunc();
let frac = d.minus(int);
if (!preserveSign) frac = frac.abs();
return frac.toNumber();
}
}
return preserveSign && isNegative ? -dec : dec;
}
// fallback for scientific notation or non-decimal input
const d = new Decimal(input);
const int = d.trunc();
let frac = d.minus(int);
if (!preserveSign) frac = frac.abs();
return frac.toNumber();
}
throw new TypeError('Input must be a number or a string');
}
The following is shorter for similar results, but slower:
import Decimal from 'decimal.js';
function getDecimalPart(input, preserveSign = false) {
const isNumber = typeof input === 'number';
const isString = typeof input === 'string';
if (!isNumber && !isString) throw new TypeError('Input must be a number or a string');
const str = isNumber ? String(input) : input;
const dot = str.indexOf('.');
const e = str.indexOf('e');
// Fast path: base-10 decimal (no scientific notation)
if (dot !== -1 && e === -1) {
const fracStr = str.slice(dot + 1);
if (!fracStr || Number(fracStr) === 0) return 0;
const dec = parseFloat('0.' + fracStr);
const isNeg = isNumber ? input < 0 : str[0] === '-';
return preserveSign && isNeg ? -dec : dec;
}
// Fallback: Decimal.js for scientific or precision-sensitive values
const d = new Decimal(str);
const frac = d.minus(d.trunc());
return preserveSign || (isNumber && input < 0) || (isString && str[0] === '-')
? frac.toNumber()
: frac.abs().toNumber();
}
If speed is the most important factor, and you never use scientific notation, then use the following code. It will be 95% faster in average than the previous function. If you need it as a float, just add const f = parseFloat( result ) in the end.
If the decimal part equals zero, "0.0" will be returned. Null, NaN and undefined numbers are not tested.
function decPartAsStr(n) {
const nstring = (n + ""),
nindex = nstring.indexOf("."),
result = "0." + (nindex > -1 ? nstring.substring(nindex + 1) : "0");
return result;
}
n = Math.floor(n);is only returning your desired result (the integer portion) for non-negative numbers% 1not% 2decimalPart = number - Math.floor(number)further, you can add precision to it.parseFloat(decimalPart.toPrecision(3))// floating point with precision till 3 digits