javascript 取商_JavaScript取整食谱

javascript 取商

Very often calculations in JavaScript produce results that don’t quite fall within the ranges we want, or generate numbers that need to be “cleaned up” before use. Exactly what happens to those numbers - rounding up or down, set within a range, or being “clipped” to a certain number of decimal places - depends on what you want to use them for.

通常, JavaScript中的计算结果不会完全落在我们想要的范围内,或者生成的数字在使用前需要“清理”。 这些数字到底发生了什么(向上舍入或向下舍入,在一个范围内设置或“固定”到某个小数位数)取决于您要使用它们的目的。

为什么要四舍五入? (Why Round Numbers?)

One of the curious aspects of JavaScript is that it doesn’t actually store integers: instead, it thinks of numbers as floating point binaries. This, combined with the fact that many fractions can’t be expressed in a finite number of decimal places, means that JavaScript can create results like the following (using the console):

JavaScript的一个令人好奇的方面是它实际上并不存储整数:而是将数字视为浮点二进制。 结合许多分数不能用有限的小数位表示的事实,这意味着JavaScript可以创建如下结果(使用console ):

0.1 * 0.2;
> 0.020000000000000004

For practical purposes, this imprecision won’t matter in the vast majority of cases - we’re talking about an error of 2 quintillionths - but it is a little frustrating. It can also introduce slightly odd-looking results when dealing with numbers that represent values of currencies, percentages, or file sizes. To fix these representations, we need to round the results, or set decimal precision.

出于实际目的,这种不精确性在绝大多数情况下都无关紧要-我们所说的误差是2十分之几-但这有点令人沮丧。 当处理代表货币值,百分比或文件大小的数字时,它也可能会带来看起来有些奇怪的结果。 要修复这些表示形式,我们需要对结果取整或设置小数精度。

Rounding numbers has many other practical applications: if a user is manipulating a range element, for example, we may want to round the associated value to the nearest whole number, rather than dealing with a decimal.

舍入数字还有许多其他实际应用:例如,如果用户正在操作range元素 ,我们可能希望将关联的值舍入到最接近的整数,而不是处理小数。

舍入十进制数 (Rounding Decimal Numbers)

To clip a decimal number, use the toFixed() or toPrecision methods. Both take a single argument that determines, respectively, how many significant digits (i.e. the total number of digits used in the number) or decimal places (the number of digitals after the decimal point) to include in the result:

要裁剪十进制数字,请使用toFixed()toPrecision方法。 两者都采用一个参数,分别确定要在结果中包括多少个有效数字(即,数字中使用的数字总数)或小数位(小数点的数字数):

  • If no argument is specified for toFixed(), the default is 0, i.e. no decimal places; the argument has a maximum value of 20.

    如果没有为toFixed()指定参数,则默认值为0,即不带小数位;否则为0。 该参数的最大值为20。

  • if no argument is specified for toPrecision, the number is unchanged.

    如果没有为toPrecision指定参数,则数字不变。

var randNum = 6.25;
randNum.toFixed();
> "6"

Math.PI.toPrecision(1);
> "3"

var randNum = 87.335;
randNum.toFixed(2);
> "87.33"

var randNum = 87.337;
randNum.toPrecision(3);
> "87.3"

重要的提示 (Important Note)

Both toFixed() and toPrecision() return the rounded string representation of the result, rather than a number. This means that “adding” rounded to randNum in the first example above will result in a concatenation, not the number you might expect:

toFixed()toPrecision()返回结果的舍入字符串表示形式 ,而不是数字。 这意味着在上面的第一个示例中将“加” roundedrandNum将导致串联而不是您可能期望的数字:

console.log(randNum + rounded);
> "6.256"

If you want the result to be an actual number, use parseFloat on it:

如果希望结果为实际数字,请在其上使用parseFloat

var randNum = 6.25;
var rounded = parseFloat(randNum.toFixed(1));
console.log(rounded);
> 6.3

(Note that values of 5 are rounded up, except in rare occasions; for a better solution, see below.)

(注意,第5值向上舍入,除了在罕见的情况下;对于更好的解决方案,见下文)

toFixed() and toPrecision() are also useful methods to pad out a whole number to include decimal places, which can be especially handy when dealing with numbers that represent currencies:

toFixed()toPrecision()也是填充整数以包括小数位的有用方法,在处理代表货币的数字时尤其方便:

var wholeNum = 1
var dollarsCents = wholeNum.toFixed(2);
console.log(dollarsCents);
> "1.00"

Note that toPrecision will produce results in scientific notation if there are more integer digits in the number than the precision amount:

请注意,如果数字中的整数位数多于精度数值,则toPrecision将产生科学计数法的结果:

var num = 123.435
num.toPrecision(2);
> "1.2e+2"

避免小数舍入错误 (Avoiding Decimal Rounding Errors)

In some cases, both toFixed and toPrecision will round values of 5 down rather than up:

在某些情况下, toFixedtoPrecision会将5向下 toPrecision整而不是向上 toPrecision整:

var numTest = 1.005;
numTest.toFixed(2);
> 1;

The result of the calculation above should be 1.01, not 1. If avoiding this error is important, I’d recommend a solution suggested by Jack L Moore that uses exponential numbers for the calculation:

上面的计算结果应该是1.01而不是 1 。 如果避免发生此错误很重要,我建议使用Jack L Moore建议的解决方案,该解决方案使用指数数进行计算:

function round(value, decimals) {
    return Number(Math.round(value+'e'+decimals)+'e-'+decimals);
}

To use:

使用方法:

round(1.005,2);
> 1.01

If you want an even more robust rounding solution than the one shown here, one is available on MDN.

如果您想要一种比此处显示的解决方案更强大的舍入解决方案,则可以在MDN上使用

Epsilon舍入 (Epsilon Rounding)

An alternative method of rounding decimals was introduced with ES6 (aka JavaScript 2015). “Machine epsilon” provides a reasonable margin of error when comparing two floating point numbers. Without rounding, comparisons can yield results like the following:

ES6(aka JavaScript 2015)引入了另一种四舍五入小数的方法。 比较两个浮点数时, “机器ε”可提供合理的误差范围。 不进行四舍五入, 比较会产生如下结果:

0.1 + 0.2 === 0.3
> false

Math.EPSILON can be used in a function to produce correct comparisons:

Math.EPSILON可以在函数中使用以产生正确的比较:

function epsEqu(x, y) {
    return Math.abs(x - y) < Number.EPSILON * Math.max(Math.abs(x), Math.abs(y));
}

The function takes two arguments: one carrying the calculation, the other the (rounded) expected result. It returns the comparison of the two:

该函数有两个参数:一个参数进行计算,另一个参数(取整)。 它返回两者的比较:

epsEqu(0.1 + 0.2, 0.3)
> true

Every current modern browser supports ES6 math functions, but if you want to gain support in older browsers such as IE 11, there are polyfills available.

当前的每个现代浏览器都支持ES6数学功能,但是如果您想在IE 11等较旧的浏览器中获得支持,则可以使用polyfill

截断小数 (Truncating Decimal Numbers)

All the techniques shown so far do some kind of rounding to decimal numbers. To truncate a positive number to two decimal places, multiply it by 100, truncate it, then divide the result by 100:

到目前为止显示的所有技术都进行了某种四舍五入到十进制数的操作。 要将正数截断为两位小数,请将其乘以100,截断然后将结果除以100:

function truncated(num) {
    return Math.trunc(num * 100) / 100;
}

truncated(3.1416)
> 3.14

If you want something with a bit more adaptability, you can take advantage of the bitwise double tilde operator:

如果您想要更多的适应性,可以利用按位双波浪号运算符:

function truncated(num, decimalPlaces) {    
    var numPowerConverter = Math.pow(10, decimalPlaces); 
    return ~~(num * numPowerConverter)/numPowerConverter;
}

To use:

使用方法:

var randInt = 35.874993;
truncated(randInt,3);
> 35.874

I’ll have more to say about bitwise operations in a future article.

在以后的文章中,我将更多地介绍按位运算。

四舍五入到最接近的数字 (Rounding To The Nearest Number)

To round a decimal number up or down to the nearest whole number, depending on which is closest, use Math.round():

要将十进制数向上或向下舍入为最接近的整数(取决于最接近的整数Math.round() ,请使用Math.round()

Math.round(4.3)
> 4

Math.round(4.5)
> 5

Note that “half values” like .5 round up.

请注意,“。半值”如.5 向上舍入。

四舍五入到最接近的整数 (Rounding Down To The Nearest Whole Number)

If you always want to round down, use Math.floor:

如果你总是想回合下来 ,用Math.floor

Math.floor(42.23);
> 42

Math.floor(36.93);
> 36

Note that this “down” rounding direction is true for all numbers, including negatives. Think of a skyscraper with an infinite number of floors, including basement levels (representing the negative numbers). If you’re in an elevator between basement levels 2 and 3 (represented by a value of -2.5), Math.floor will take you to -3:

请注意,此“向下”舍入方向适用于所有数字,包括负数。 想一想摩天大楼的楼层数是无限的,包括地下楼层(代表负数)。 如果您在2到3级地下室之间(由-2.5表示),则Math.floor会将您带到-3:

Math.floor(-2.5);
> -3

If want to avoid this behaviour, use Math.trunc, supported in all modern browsers (except IE/Edge):

如果要避免这种行为,请使用所有现代浏览器(IE / Edge除外)都支持的Math.trunc

Math.trunc(-41.43);
> -41

MDN also provides a three-line polyfill to gain Math.trunc support in older browsers and IE/Edge.

MDN还提供了三行Math.trunc以在较旧的浏览器和IE / Edge中获得Math.trunc支持

舍入最接近的整数 (Rounding Up To The Nearest Whole Number)

Alternatively, if you always want to round up, use Math.ceil. Again, think of that infinite elevator: Math.ceil will always go “upwards”, regardless of whether the number is negative or not:

或者,如果你总是希望围捕 ,使用Math.ceil 。 再次考虑一下无限电梯: Math.ceil将始终“向上”,无论数字是否为负:

Math.ceil(42.23);
> 43

Math.ceil(36.93);
> 37
Math.ceil(-36.93); -36

四舍五入到数字的最近倍数 (Rounding Up/Down To The Nearest Multiple of a Number)

If we want to round to the nearest multiple of 5, the easiest way is to create a function that divides the number by 5, rounds it, then multiplies it by the same amount:

如果我们想四舍五入到最接近的5的倍数,最简单的方法是创建一个将数字除以5的函数,将其四舍五入,然后将其乘以相同的数量:

function roundTo5(num) {
    return Math.round(num/5)*5;
}

To use it:

要使用它:

roundTo5(11);
> 10

If you were rounding to multiples of different numbers, we could make this function more general by passing the function both the initial number and the multiple:

如果四舍五入为不同数字的倍数,我们可以通过传递初始数字和倍数来使该函数更通用:

function roundToMultiple(num, multiple) {
    return Math.round(num/multiple)*multiple;
}

To use it, include both the number and the multiple in the call to the function:

要使用它,请在函数调用中同时包含数字和倍数:

var initialNumber = 11;
var multiple = 10;
roundToMultiple(initialNumber, multiple);
> 10;

To exclusively round up or round down; substitute ceil or floor for round in the function.

专心地向上或向下取整: 在功能中用ceilfloor代替round

夹紧数到一定范围 (Clamping Number To a Range)

There are plenty of times when you may receive a value x that needs to be within the bounds of a range. For example, you may need a value from 1 to 100, but receive a value of 123. To fix this, we can use min (which will always return the smallest of a set of numbers) and max (the largest member of any set of numbers). Using the 1 to 100 example:

很多时候,您可能会收到一个必须在范围范围内的值x 。 例如,您可能需要一个1100的值,但是会收到123的值。 为了解决这个问题,我们可以使用min (总是返回一组数字中的smallest数)和max (任何一组数字中的最大数)。 以1100为例:

var lowBound = 1;
var highBound = 100;
var numInput = 123;
var clamped = Math.max(lowBound, Math.min(numInput, highBound));
console.log(clamped);
> 100;

Again, this could be turned into a function, or possibly an extension of the Number class, a variation first suggested by Daniel X. Moore:

同样,这可以被转换为一个函数,或者可能是Number类的扩展,这是Daniel X. Moore首先提出的一种变体:

Number.prototype.clamp = function(min, max) {
  return Math.min(Math.max(this, min), max);
};

To use it:

要使用它:

(numInput).clamp(lowBound, highBound);

高斯舍入 (Gaussian Rounding)

Gaussian rounding, also known as “bankers” rounding, convergent rounding, Dutch rounding, and odd–even rounding, is a method of rounding without statistical bias; regular rounding has a native upwards bias. Gaussian rounding avoids this by rounding to the nearest even number. The best solution I’m aware of is by Tim Down:

高斯舍入,也称为“银行家”舍入,收敛舍入舍入,荷兰舍入和奇偶舍入,是一种无统计偏差的舍入方法; 常规取整具有固有的向上偏差。 高斯舍入通过舍入到最接近的偶数来避免这种情况。 我知道的最好的解决方案是Tim Down

function gaussRound(num, decimalPlaces) {
    var d = decimalPlaces || 0,
    m = Math.pow(10, d),
    n = +(d ? num * m : num).toFixed(8),
    i = Math.floor(n), f = n - i,
    e = 1e-8,
    r = (f > 0.5 - e && f < 0.5 + e) ?
		((i % 2 == 0) ? i : i + 1) : Math.round(n);
    return d ? r / m : r;
}

Examples in use:

使用示例:

gaussRound(2.5)
> 2

gaussRound(3.5)
> 4

gaussRound(2.57,1)
> 2.6

CSS中的小数 (Decimals in CSS)

Since JavaScript is often used to generate positional or transform information for HTML elements, you might wonder what happens if we generate decimal values for elements:

由于JavaScript通常用于生成HTML元素的位置或变换信息,因此您可能想知道如果我们为元素生成十进制值会发生什么:

#box { width: 63.667731993px; }

The good news is that modern browsers will respect decimal values in the box model, including percentage and pixel measurements.

好消息是, 现代浏览器将使用盒模型中的十进制值 ,包括百分比和像素尺寸。

翻译自: https://thenewcode.com/895/JavaScript-Rounding-Recipes

javascript 取商

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值