亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

在 Javascript 中將數字 0.005 向下舍入

在 Javascript 中將數字 0.005 向下舍入

萬千封印 2022-06-16 15:54:15
有沒有辦法將數字 0.005 向下舍入。例如:5.425是要四舍五入到5.422.336是要四舍五入到2.340.5556是要四舍五入到0.56更新:在點之后我并不總是有 3 位數字,我可以擁有更多。像5.555556, 12.3456789, 等等已經嘗試過,parseFloat(number).toFixed(2)但在某些情況下它并沒有真正起作用,像0.555輸出這樣的值將0.56代替0.55提前致謝
查看完整描述

2 回答

?
大話西游666

TA貢獻1817條經驗 獲得超14個贊

問題是,JavaScript 不知道5.425. 計算機的浮點實現以及大多數編程語言的浮點實現都是基于二進制的,而不是基于十進制的(參見 IEEE 754)。因此,每個掃描的數字首先四舍五入到最接近的可能值:


5.425  .toPrecision(18); // result "5.42499999999999982"  => ToFixed(2)="5.42"

2.336  .toPrecision(18); // result "2.33599999999999985"  => ToFixed(2)="2.34"

0.5556 .toPrecision(18); // result "0.555599999999999983" => ToFixed(2)="0.56"

并將這些掃描結果用于進一步處理。所以使用的結果toFixed(2)是預期的并且絕對正確。


并且不要相信其他解決方案(有時稱為betterToFixed())來解決此問題。他們對其他數字有疑問,因為許多作者不了解幕后的數學。


查看完整回答
反對 回復 2022-06-16
?
人到中年有點甜

TA貢獻1895條經驗 獲得超7個贊

你說你想5.425四舍五入,5.42但你想5.555556四舍五入5.556。這意味著您正在執行向下舍入(或可能是向零舍入)操作,而不是在“正常”回合中增加(或遠離零,取決于)。


我能想到的唯一方法是在四舍五入的每個階段從數字的最后一位中減去一個,如下所示:


// Round the given number to the given number of places, but rounding ties down

// (0.5 rounds to 0 instead of 1, 0.55 rounds to 0.5 instead of 0.6, etc.)

function roundTiesDown(n, places) {

    if (places < 1) {

        throw new Error(`Received places=${places}, but must be >=1`);

    }

    let currentPlaces = significantFractionalPlaces(n)

    // Round ties down at each level, e.g. (if places = 2):

    // 0.55556 => 0.5556

    // 0.5556 => 0.556

    // 0.556 => 0.56

    // and

    // 0.55555 => 0.5555 (would be 0.5556 with "normal" rounding)

    // 0.5555 => 0.555

    // 0.555 => 0.55

    while (currentPlaces > places) {

        const subtrahend = 1 / Math.pow(10, currentPlaces);

        --currentPlaces;

        const multiplier = Math.pow(10, currentPlaces);

        n = Math.round((n - subtrahend) * multiplier) / multiplier;

    }

    return n;

}

現場示例:

// Get a function to convert numbers to string without going to scientific notation

let numberToString;

if (typeof Intl === "object" && typeof Intl.NumberFormat === "function") {

    // Intl.NumberFormat lets us do this properly

    const format = new Intl.NumberFormat(undefined, {

        style: "decimal",

        useGrouping: false,

        maximumFractionDigits: 20

    });

    numberToString = n => format.format(n);

} else {

    // Fall back to toString on platforms without Intl.NumberFormat

    // (all major browsers have it, including IE11 -

    // https://caniuse.com/#feat=mdn-javascript_builtins_intl_numberformat)

    const rexContainsE = /e/i;

    numberToString = n => {

        const str = n.toString();

        if (rexContainsE.test(str)) {

            // Went to scientific notation

            throw new Error("Can't handle numbers this big on this platform");

        }

        return str;

    };

}


// Get the currentPlaces number of significant places in the given number

function significantFractionalPlaces(n) {

    const str = numberToString(n);

    const idx = str.indexOf(".");

    return idx === -1 ? 0 : str.length - idx - 1;

}


// Round the given number to the given number of places, but rounding ties down

// (0.5 rounds to 0 instead of 1, 0.55 rounds to 0.5 instead of 0.6, etc.)

function roundTiesDown(n, places) {

    if (places < 1) {

        throw new Error(`Received places=${places}, but must be >=1`);

    }

    let currentPlaces = significantFractionalPlaces(n)

    // Round ties down at each level, e.g. (if places = 2):

    // 0.55556 => 0.5556

    // 0.5556 => 0.556

    // 0.556 => 0.56

    // and

    // 0.55555 => 0.5555 (would be 0.5556 with "normal" rounding)

    // 0.5555 => 0.555

    // 0.555 => 0.55

    while (currentPlaces > places) {

        const subtrahend = 1 / Math.pow(10, currentPlaces);

        --currentPlaces;

        const multiplier = Math.pow(10, currentPlaces);

        /* For your real function, use this:

        n = Math.round((n - subtrahend) * multiplier) / multiplier;

        instead of the following lines using `rounded`

        */

        const rounded = Math.round((n - subtrahend) * multiplier) / multiplier;

        if (verbose) {

            log("detail", `Rounded ${n} to ${rounded}`);

        }

        n = rounded;

    }

    return n;

}


// ===== Testing


const cbVerbose = document.querySelector("input[type=checkbox]");

const btnRun = document.querySelector("input[type=button]");

const output = document.querySelector(".output");

const errors = document.querySelector(".errors");


function log(cls, msg) {

    /*

    output.insertAdjacentText("beforeend", "\r\n" + msgs.join(" "));

    */

    const div = document.createElement("div");

    div.className = cls;

    div.textContent = msg;

    output.appendChild(div);

}


let verbose = cbVerbose.checked;


function test(n, expected) {

    const rounded = roundTiesDown(n, 2);

    const good = rounded === expected;

    log(

        good ? "good" : "error",

        `${n} => ${rounded} ${good ? "OK" : `<== ERROR, expected ${expected}`}`

    );

    return good ? 0 : 1;

}


function runTests() {

    verbose = cbVerbose.checked;

    output.textContent = "";

    const errorcount =

        test(5.425, 5.42) +

        test(5.555556, 5.56) +

        test(12.3456789, 12.35) +

        test(1.125, 1.12) +

        test(2.336, 2.34) +

        test(2, 2) +

        test(-5.425, -5.43);

    errors.textContent = errorcount === 0 ? "All passed" : `Errors: ${errorcount}`;

    errors.className = errorcount === 0 ? "good" : "error";

}


btnRun.addEventListener("click", runTests);

runTests();

html {

    box-sizing: border-box;

    font-family: sans-serif;

}

*, *:before, *:after {

    box-sizing: inherit;

}

html, body {

    height: 100%;

    overflow: hidden;

    padding: 0;

    margin: 0;

}

body {

    padding: 4px;

    display: flex;

    flex-direction: column;

    font-size: 14px;

}


.panel {

    order: 1;

    border-bottom: 1px solid black;

    padding-bottom: 2px;

}

.output {

    order: 2;

    flex-grow: 1;

    white-space: pre;

    font-family: monospace;

    overflow: auto;

}


.good {

    color: #060;

}

.error {

    color: #C00;

}

.detail {

    color: #aaa;

}

<div class="panel">

    <label style="user-select: none">

        <input type="checkbox">

        Verbose output

    </label>

    <input type="button" value="Run Tests">

    <span class="errors"></span>

</div>

<div class="output"></div>


請注意,最后一個結果為負數。如果您想向零舍入而不是“向下”,請更改此行:


n = Math.round((n - subtrahend) * multiplier) / multiplier;

對此,它允許 的符號n:


n = Math.round((n + (n < 0 ? subtrahend : -subtrahend)) * multiplier) / multiplier;

并更改函數的名稱,因為它不再向下舍入(也許roundTiesToZero)。


現場示例:

// Get a function to convert numbers to string without going to scientific notation

let numberToString;

if (typeof Intl === "object" && typeof Intl.NumberFormat === "function") {

    // Intl.NumberFormat lets us do this properly

    const format = new Intl.NumberFormat(undefined, {

        style: "decimal",

        useGrouping: false,

        maximumFractionDigits: 20

    });

    numberToString = n => format.format(n);

} else {

    // Fall back to toString on platforms without Intl.NumberFormat

    // (all major browsers have it, including IE11 -

    // https://caniuse.com/#feat=mdn-javascript_builtins_intl_numberformat)

    const rexContainsE = /e/i;

    numberToString = n => {

        const str = n.toString();

        if (rexContainsE.test(str)) {

            // Went to scientific notation

            throw new Error("Can't handle numbers this big on this platform");

        }

        return str;

    };

}


// Get the currentPlaces number of significant places in the given number

function significantFractionalPlaces(n) {

    const str = numberToString(n);

    const idx = str.indexOf(".");

    return idx === -1 ? 0 : str.length - idx - 1;

}


// Round the given number to the given number of places, but rounding ties down

// (0.5 rounds to 0 instead of 1, 0.55 rounds to 0.5 instead of 0.6, etc.)

function roundTiesToZero(n, places) {

    if (places < 1) {

        throw new Error(`Received places=${places}, but must be >=1`);

    }

    let currentPlaces = significantFractionalPlaces(n)

    // Round ties down at each level, e.g. (if places = 2):

    // 0.55556 => 0.5556

    // 0.5556 => 0.556

    // 0.556 => 0.56

    // and

    // 0.55555 => 0.5555 (would be 0.5556 with "normal" rounding)

    // 0.5555 => 0.555

    // 0.555 => 0.55

    while (currentPlaces > places) {

        const subtrahend = 1 / Math.pow(10, currentPlaces);

        --currentPlaces;

        const multiplier = Math.pow(10, currentPlaces);

        /* For your real function, use this:

        n = Math.round((n + (n < 0 ? subtrahend : -subtrahend)) * multiplier) / multiplier;

        instead of the following lines using `rounded`

        */

        const rounded = Math.round((n + (n < 0 ? subtrahend : -subtrahend)) * multiplier) / multiplier;

        if (verbose) {

            log("detail", `Rounded ${n} to ${rounded}`);

        }

        n = rounded;

    }

    return n;

}


// ===== Testing


const cbVerbose = document.querySelector("input[type=checkbox]");

const btnRun = document.querySelector("input[type=button]");

const output = document.querySelector(".output");

const errors = document.querySelector(".errors");


function log(cls, msg) {

    /*

    output.insertAdjacentText("beforeend", "\r\n" + msgs.join(" "));

    */

    const div = document.createElement("div");

    div.className = cls;

    div.textContent = msg;

    output.appendChild(div);

}


let verbose = cbVerbose.checked;


function test(n, expected) {

    const rounded = roundTiesToZero(n, 2);

    const good = rounded === expected;

    log(

        good ? "good" : "error",

        `${n} => ${rounded} ${good ? "OK" : `<== ERROR, expected ${expected}`}`

    );

    return good ? 0 : 1;

}


function runTests() {

    verbose = cbVerbose.checked;

    output.textContent = "";

    const errorcount =

        test(5.425, 5.42) +

        test(5.555556, 5.56) +

        test(12.3456789, 12.35) +

        test(1.125, 1.12) +

        test(2.336, 2.34) +

        test(2, 2) +

        test(-5.425, -5.42);

    errors.textContent = errorcount === 0 ? "All passed" : `Errors: ${errorcount}`;

    errors.className = errorcount === 0 ? "good" : "error";

}


btnRun.addEventListener("click", runTests);

runTests();

html {

    box-sizing: border-box;

    font-family: sans-serif;

}

*, *:before, *:after {

    box-sizing: inherit;

}

html, body {

    height: 100%;

    overflow: hidden;

    padding: 0;

    margin: 0;

}

body {

    padding: 4px;

    display: flex;

    flex-direction: column;

    font-size: 14px;

}


.panel {

    order: 1;

    border-bottom: 1px solid black;

    padding-bottom: 2px;

}

.output {

    order: 2;

    flex-grow: 1;

    white-space: pre;

    font-family: monospace;

    overflow: auto;

}


.good {

    color: #080;

}

.error {

    color: #C00;

}

.detail {

    color: #aaa;

}

<div class="panel">

    <label style="user-select: none">

        <input type="checkbox">

        Verbose output

    </label>

    <input type="button" value="Run Tests">

    <span class="errors"></span>

</div>

<div class="output"></div>


查看完整回答
反對 回復 2022-06-16
  • 2 回答
  • 0 關注
  • 127 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號