Rounding to significant digits - Missing zeros

I am currently creating a math package based on JavaScript that focuses on rounding on various significant digits (SF) , but I ran into a problem I'm trying to solve.

More on this issue later, but first a little background for you.

The program is designed to select a completely random number in a given range and then automatically generate this number corresponding to significant digits; eg:

Random number: 0.097027 S.Fs: 9, 7, 0, 2, 7


Here is a screenshot of what I did for the visual presentation:

enter image description here

, , , "SF" , , 1, 2, 3 4 S.Fs .

SF (1-4) , X SF , , SF .

, , . ...

, (0.097027); , , 4 S.F .

3 SF, :

: 0.097027 3 S.F Rounded Up/Down/Off: 0.0970

, :

: 0.097027 3 S.F Rounded Up/Down/Off: 0.097

. , , .


, , , . toFixed(x), toFixed(4), , , 5 , . 89.404 > 10, . `0,000020615.

, , toFixed /, toFixed(n) , , , ?

:

function generateNum() {

do {
        genNumber = Math.random() * Math.pow (10, randomRange(-5, 5));

        //Round
        genNumber = roundToNSF(genNumber, 5, 0);

        // This number must contain >1 digit which is 1 to 9 inclusive otherwise we may have e.g. 100. Rounding 100
    } 

while (!countNonZero(genNumber) || genNumber < 1E-05 || genNumber == 0);

    //Round
    genNumber = roundToNSF(genNumber, 5, 0);


    genNumber = String(genNumber);
    genNumber = Number(genNumber);
}

//----------------------------------------------------------------------------

function randomRange(min, max) {

/**
 * Returns a random integer between min (inclusive) and max (inclusive)
 * Using Math.round() will give you a non-uniform distribution!
 */

return Math.floor(Math.random() * (max - min + 1)) + min;

} 

//---------------------------------------------------------------------------
//Click SF3 Button to reveal the data
function showSF3() {

//Remove any CSS properties on the buttons from previous use
removeButtonCSS();

document.getElementById('SFRounded').style.display = "block";
document.getElementById('scale').style.display = "block";
document.getElementById("SF3").className = document.getElementById("SF3").className + "buttonClick";  // this removes the blue border class

//Clear text
deleteRounded();
deleteScale();

//Run calculation
calculateAnswer();

//alert(genNumber.toFixed(4));

for (i = 3; i < 4; i++)

    {
         //Add The new data
         sfRoundedTextBlock = document.getElementById('SFRounded');

         //alert(downArray[i].toFixed(4));

         //Data output to HTML.

         sfRoundedTextBlock.innerHTML = sfRoundedTextBlock.innerHTML + '<p><strong>Number: </strong></br>' + String(genNumber) + 
         '</br>' + '<strong>Rounded down to ' + i + ' SF:</br></strong>' + downArray[i] + '</br>' + 
         '<strong>Rounded up to ' + i + ' SF:</br></strong>' + upArray[i] + '</br><strong>Rounded off to ' + i + ' SF:</br></strong>' 
         + roundedArray[i] + '</br>' + '(See the scale below for why we choose <strong>' + roundedArray[i] + '</strong> as the rounded off value.)</p>';

    }

}

//----------------------------------------------------------------------

var roundedArray = [];
var upArray = [];
var downArray = [];
var temp;

function calculateAnswer() {
//Clear Arrays
roundedArray = [];
upArray = [];
downArray = [];

// Work out the answer:
for (i = 0; i < 4; i++) {

    var nSF = i + 1;
    // Round OFF ...
    temp = roundToNSF(genNumber, nSF, 0);
    // We actually have to do this twice ...
    roundedArray[nSF] = roundToNSF(temp, nSF, 0);

    // Round UP ...
    upArray[nSF] = roundToNSF(genNumber, nSF, 1);

    // Round DOWN ...
    downArray[nSF] = roundToNSF(genNumber, nSF, -1);
    // e.g. x = 0.0098 rounded to 1SF is 0.010 initially (take the log of 0.0098 and try it!).
};  
};


//-------------------------------------------------------------------------

//Globals
var aNumber;
var digits;
var way;

function roundToNSF(aNumber, digits, way){
// Round a number to n significant figures (can use roundToNDP provided we know how many decimal places):
    if (way == undefined) { way = 0; }; // default is round off

if (aNumber !=0) {

    if (aNumber > 0)
        { 
            z = log10(aNumber); 
        } 
        else 
            { 
                z = log10(-aNumber); 
            };

    z = Math.floor(z);

    var nDP = digits - z - 1; // Rounding to nDP decimal places is equivalent to rounding to digits significant figures ...

    var roundedNumber = roundToNDP(aNumber, nDP, way);

} 
else {

    roundedNumber = aNumber; // Number is zero ...
};

return Number(roundedNumber);
};

//---------------------------------------------------------------------------------

Update:

- , , , indexOf("."), (dp).

, dp, [1-9].

var genNumber =  0.097027;
var rString = String(genNumber);
var positionofDP = rString.indexOf(".");
var regexp = /[1-9]/;
var positionofNonZero = Number(rString.search(regexp, positionofDP));  // Output would be '5'

, , "" .

, "true", //, , "0", .

, 5 12 .

, toFixed(i)? .

+4
2

, , .

, toFixed toPrecision. , , , ("."), toFixed.

, , 12 , toPrecision. "SF" (1-4) toPrecision, , SF1:

    sfRoundedTextBlock.innerHTML = sfRoundedTextBlock.innerHTML + '<p><strong>Number: </strong></br>' + String(genNumber) + 
    '</br>' + '<strong>Rounded down to ' + i + ' SF:</br></strong>' + downArray[i].toPrecision(1) + '</br>' + 
    '<strong>Rounded up to ' + i + ' SF:</br></strong>' + upArray[i].toPrecision(1) + '</br><strong>Rounded off to ' + i + ' SF:</br></strong>' 
    + roundedArray[i].toPrecision(1) + '</br>' + '(See the scale below for why we choose <strong>' + roundedArray[i].toPrecision(1) + '</strong> as the rounded off value.)</p>';

    //Add The new scale data (Rounded Down)
    downTextBlock = document.getElementById('down');
    document.getElementById("down").innerHTML = String(downArray[i].toPrecision(1));

    //Add The new scale data (Rounded Up)
    upTextBlock = document.getElementById('up');
    document.getElementById("up").innerHTML = String(upArray[i].toPrecision(1));

, , . , , . 21819 1 SF, 2e+4 20000.

, , , , / [a-z]. -, , parseFloat, :

//Convert Up, Down and Rounded into Strings based on their precision
        var upString = String(upArray[i].toPrecision(1));
        var downString = String(downArray[i].toPrecision(1));
        var roundedString = String(roundedArray[i].toPrecision(1));
        //Set up a regexp to search for characters [a-z], i.e. non-numeric
        var regexp = /[a-z]/g; 
        //Search the up, down and rounded strings for non-numeric characters
        var upResult = upString.match(regexp);
        var downResult = downString.match(regexp);
        var roundedResult = roundedString.match(regexp);
        //If any of these strings contain a letter (non-numeric) we need to add in parseFloat to strip away the scientific notation included.
        var containsChar = false;

        if (upResult != null || downResult != null || roundedResult != null)

            {
                containsChar = true;
                //alert("There is SN included here");
            }

         //Add The new data
         sfRoundedTextBlock = document.getElementById('SFRounded');

        if (containsChar == true)

        {
            sfRoundedTextBlock.innerHTML = sfRoundedTextBlock.innerHTML + '<p><strong>Number: </strong></br>' + String(genNumber) + 
            '</br>' + '<strong>Rounded down to ' + i + ' SF:</br></strong>' + parseFloat(downArray[i].toPrecision(1)) + '</br>' + 
            '<strong>Rounded up to ' + i + ' SF:</br></strong>' + parseFloat(upArray[i].toPrecision(1)) + '</br><strong>Rounded off to ' + i + ' SF:</br></strong>' 
            + parseFloat(roundedArray[i].toPrecision(1)) + '</br>' + '(See the scale below for why we choose <strong>' + parseFloat(roundedArray[i].toPrecision(1)) + '</strong> as the rounded off value.)</p>';

            //Add The new scale data (Rounded Down)
            downTextBlock = document.getElementById('down');
            document.getElementById("down").innerHTML = String(parseFloat(downArray[i].toPrecision(1)));

            //Add The new scale data (Rounded Up)
            upTextBlock = document.getElementById('up');
            document.getElementById("up").innerHTML = String(parseFloat(upArray[i].toPrecision(1)));
        }  

, , , , .

0

, Int, .

: http://jsfiddle.net/5rw5G/4/

, .

function getRoundedSFs(num, SFCount) {    
    // Match every "leading zeros" before and after the .
    var matches = num.toString().match(/^-?(0+)\.(0*)/);

    // starting with "0."
    if (matches) { 
        var firstIndex = matches[0].length;
        var prefix = matches[0];

        sf = Number(num.toString().substring(firstIndex, firstIndex + SFCount + 1));
        sf = Math.round(sf / 10);
        sf = prefix + sf.toString();
        return Number(sf).toFixed(matches[2].length+SFCount);
    } 

    // starting with something else like -5.574487436097115
    else { 
        matches = num.toString().match(/^(-?(\d+))\.(\d+)/);
        var decimalShift = SFCount - matches[2].length;        
        var rounded = Math.round(num * Math.pow(10, decimalShift));       
        rounded /= Math.pow(10, decimalShift);
        return rounded.toFixed(decimalShift);
    }
}
+3

Source: https://habr.com/ru/post/1543582/


All Articles