简体   繁体   English

JavaScript仅显示X个小数位,不舍入

[英]JavaScript display only X decimal places, no rounding

I know this question has been asked before but there are a few issues with the answers that have been given that I am trying to fix. 我知道以前曾问过这个问题,但是我尝试解决的答案有一些问题。

Here is one I found with the following answer: 这是我用以下答案找到的一个:

function calc(number) {
    var num = number;
    var with2Decimals = num.toString().match(/^-?\d+(?:\.\d{0,2})?/)[0];
    return with2Decimals
}

Here is another one I found that works in the same way that I like a little better: 这是我发现的另一件作品,其工作方式与我喜欢的要好一些:

function decimalFix(numToBeTruncated, numOfDecimals) { 
    var theNumber = numToBeTruncated.toString(); 
    var pointIndex = theNumber.indexOf('.');
    return +(theNumber.slice(0, pointIndex > -1 ? ++numOfDecimals + pointIndex : undefined)); 
}

The issue: 问题:

For the most part they work nicely except for extremely large decimal numbers. 在大多数情况下,它们都可以正常工作,但十进制数字很大。 For example, the number 0.00000001990202020291 reads as 1.99020202029e-8 in javascript so instead of giving me 0.000000019 if I wanted 9 decimal places in it would give me 1.99020202 which is extremely off base. 例如,在JavaScript中,数字0.00000001990202020291读为1.99020202029e-8 ,因此如果我想在其中保留 9位小数,而不是给我0.000000019 ,它将给我1.99020202 ,这是可靠的

Why?????? 为什么??????

A lot of people have been really upset that I / other people would even want to tackle this issue because it seems unorthodox to them. 很多人真的很沮丧,我/其他人甚至想解决这个问题,因为这对他们来说似乎是不合常规的。 It mostly has to do with currency and not loosing fractions of the value if I'm only allowed to be so exact in my calculations. 如果只允许我在计算中如此精确的话,这主要与货币有关,而不是损失价值的零头。 For example there are times where I need to calculate micro transactions up to 6-8 decimal places but I'm loosing or gaining money in the process if I choose to round. 例如,有时我需要计算小额交易最多6-8个小数位,但是如果我选择四舍五入,就会失去或赚钱。

I appreciate any help or guidance someone can bring to this issue. 感谢您为这个问题提供的任何帮助或指导。

Expected results: 预期成绩:

decimalFix(0.0000000199020202029,9) // 0.000000019

You've said you need 6-8 digits to the right of the decimal, and 6-8 to the left of it (but typically more like 1-3). 您已经说过,您需要在小数点右边添加6-8位数字,并在其左边添加6-8位数字(但通常更像是1-3位)。

That's riding the edge (if really 8.8, going over the edge) of what JavaScript's number type (IEEE-754 double-precision binary floating point) can do. JavaScript的数字类型(IEEE-754双精度二进制浮点数)可以做到这一点(如果真的是8.8,就越过边缘)。 Regardless of where the decimal is, JavaScript's floating point has roughly 15 decimal digits of precision before you lose information. 不论小数点在哪里,JavaScript的浮点在丢失信息之前的精度大约为 15个小数位。 (That's not the full story by any means.) (无论如何,这不是完整的故事。)

Good news: JavaScript is getting a BigInt type you could use for this (by multiplying your values by 100,000,000 so they're whole numbers), details here . 好消息:JavaScript正在获得可用于此目的的BigInt类型(将值乘以100,000,000,因此它们是整数),请参见此处 Until then, you might consider using one of the existing "big number" libraries. 在此之前,您可以考虑使用现有的“大量”库之一。

If you need to use JavaScript's numbers, I would do it with whole numbers. 如果您需要使用JavaScript的数字,我会使用整数。 With whole numbers, your perfectly-accurate range is -Number.MAX_SAFE_INTEGER - 1 through Number.MAX_SAFE_INTEGER + 1 . 对于整数,您的精确范围是-Number.MAX_SAFE_INTEGER - 1Number.MAX_SAFE_INTEGER + 1 That's -9,007,199,254,740,992 through 9,007,199,254,740,992. 那是-9,007,199,254,740,992到9,007,199,254,740,992。 With that, you can get seven digits left of the decimal and eight right of it (or of course, eight left and seven right). 这样,您可以获得小数点左边的七位数,小数点右边的八位(或者,当然,左数八位和右七位)。 So if we're using eight digits of precision right of the decimal and seven to the left (well within limits), that's -9,999,999.99999999 through 9,999,999.99999999 . 因此,如果我们在小数点右边使用八位精度,在左边使用七位精度(在限制范围内),则是-9,999,999.999999999,999,999.99999999

Calculations would use Math.trunc to remove the fractional portion (assuming you want to truncate toward zero). 计算将使用Math.trunc删除小数部分(假设您要截断为零)。 Output without scientific notation is trivial: 没有科学计数法的输出是微不足道的:

str = String(number);
str = str.substring(0, str.length - 8) + "." + str.substr(-8);

Examples: 例子:

 function toString(number) { var str = String(number); str = str.substring(0, str.length - 8) + "." + str.substr(-8); return str; } console.log(toString(999999999999999)); console.log(toString(123456712345678)); console.log(toString(765432187654321)); 

It mostly has to do with currency and not loosing fractions of the value if I'm only allowed to be so exact in my calculations. 如果只允许我在计算中如此精确的话,这主要与货币有关,而不是损失价值的零头。 For example there are times where I need to calculate micro transactions up to 6-8 decimal places but I'm loosing or gaining money in the process if I choose to round. 例如,有时我需要计算小额交易最多6-8个小数位,但是如果我选择四舍五入,就会失去或赚钱。

 //rounding to an arbitrary precision function round(value, precision = 1) { return Math.round(value / precision) * precision } console.log("round"); console.log(round(1.23456789, 0.001)); console.log(round(1.23456789, 1 / 4)); console.log(round(Date.now(), 1000*60*60)); //the current timestamp rounded to the hour //rounding to a certain amount of decimal places function roundToDecimalPlaces(value, decimalPlaces = 0) { return round(value, "1e" + (-decimalPlaces)); } console.log("roundToDecimalPlaces"); console.log(roundToDecimalPlaces(1.23456789, 4)); console.log(roundToDecimalPlaces(0.0000000199020202029, 9)); //and truncating everything after a certain amount of decimal places function decimalFix(value, decimalPlaces = 0) { let precision = "1e" + (-decimalPlaces); return Math[value < 0 ? "ceil" : "floor"](value / precision) * precision; } console.log("decimalFix"); console.log(decimalFix(0.0000000199020202029, 9)); 
 .as-console-wrapper { top: 0; max-height: 100%!important } 


But why do you want to limit the precision in the first place? 但是,为什么首先要限制精度? If it's abount the view, and how the values are displayed, then this is the wrong approach. 如果是在视图上方,以及如何显示值,那么这是错误的方法。

Then you should check out Number#toFixed , Number#toPrecision and Number#toLocaleString 然后,您应该签出Number#toFixedNumber#toPrecisionNumber#toLocaleString

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM