# Random Number Complete Function (v3)

## Setup

function isNumber(num){
return (typeof num === 'number' && !isNaN(num));
}

function toFixed(value,precision, roundingMethod = 'round')
{
roundingMethod = roundingMethod.toLowerCase()

if(isNaN(precision)){
throw new Error("precision is NaN");
}
if(isNaN(value)){
throw new Error("value is NaN");
}
if(precision<0) precision = 0

let negative = (value<0);

value = Math.abs(value);

let fixer = Math.pow(10,precision);

if(roundingMethod == 'floor')  value = Math.floor(value * fixer) / fixer;
else if(roundingMethod == 'ceil')  value = Math.ceil(value * fixer) / fixer;
else  value = Math.round(value * fixer) / fixer;

return (negative ? (-value) : value);
}

function findPrecision(num) {
if (!isFinite(num)) return 0;
if (typeof num !== "number") num = +num;
if (isNaN(num)) return 0;

num = Math.abs(num);
if(num < 1e-16) return 16.5;
let numFix = toFixed(num,16,'floor')

let e = 1, decP = 0;
while (Math.round(num * e) / e !== num) { e *= 10; decP++; }
e = 1; let decPFix = 0;
while (Math.round(numFix * e) / e !== numFix) { e *= 10; decPFix++; }

return (decP > decPFix ? decPFix : decP);
}

function randNum(min,max, precision = true)
{
if(isNaN(min) || isNaN(max))
{
throw new Error("min or max is NaN");
}
if(min == max)  return max;

if(precision === true){
let minP = findPrecision(min)
let maxP = findPrecision(max)
if(minP==16.5) minP = 16;
if(maxP==16.5) maxP = 16;
precision = maxP > minP ? maxP : minP;

}

if(isNumber(precision)){
}
else{
return ((Math.random() * ((max+1)-min)) + min);
}
}

let opts = [
[1, 2, 2],
[0, 12, false],
[-8, 4, true],
[-1.34, 2.945, true],
[-20, -5, null],
[2.8, 0, 2],
[1.4858, 6.45, true],
[9.857203, 8.857203, 3],
[-2.3455, 2.3455, true],
[3.89, 3.456, 1],
[0, 0, true]
]

## Test runner

Testing in
TestOps/sec
"Complex" rand num
for(let i = 0, b=0; i < opts.length; ++i){
b = randNum(...opts[i])
}