简体   繁体   English

如何在JavaScript中找到小于1的最大数字

[英]How to find the largest number less than one in javascript

While searching for a way to do a faster ceil operator than ceil itself, I came upon this: 在寻找一种比ceil本身更快的ceil运算符的方法时,我想到了这一点:

var ceilX = (X + 1) >> 0

Which does a bit of bitwise magic to shave off the decimal, but ultimately fails to do a correct ceil operation because (1 + 1) >> 0 === 2 , while ceil(1) === 1. 这样做有点位魔术去掉小数,但最终由于(1 + 1) >> 0 === 2 ,而ceil(1)=== 1,最终却无法正确执行ceil操作。

There's a different question on how to do this here , but the line of thought got me wondering if there's a way to add a number that's baaaaarely less than 1 to a value and then use the bitwise shift to round it. 有一个关于如何做到这一点不同的问题在这里 ,但思想的线让我知道如果有补充一个数字,就是baaaaarely小于1的值,然后使用按位移位四舍五入它的方式。 This seems to me like it should work for everything that can be expressed as a 32-bit number, but I'm not sure how to get the number that's really close to 1. In the name of pointless micro optimization, is there a good way of doing this? 在我看来,这似乎应该适用于可以表示为32位数字的所有内容,但是我不确定如何获得真正接近1的数字。以无意义的微优化为名,这样的方式?

In non IE browsers the Number.EPSILON property represents the difference between one and the smallest value greater than one. 在非IE浏览器中, Number.EPSILON属性表示1与大于1的最小值之间的差。 So to get to your largest number less one would be 1-Number.EPSILON 因此,要获得最大的数字,请减去1-Number.EPSILON

You can also calculate an Epsilon value by recursively dividing 1 by 2 until it equals zero and then taking the number from the second last step. 您还可以通过以下方式计算Epsilon值:将1递归除以2,直到等于0,然后从倒数第二个步骤中取数字。 This will produce a smaller value than Number.EPSILON . 这将产生比Number.EPSILON小的值。

Both methods are shown in the below fiddle along with comparisons to the internal ceil function and unfortunately neither epsilon methods match the internal method exactly but do ok up to an arbitrary precision. 两种方法都在下面的小提琴中进行了显示,并与内部ceil函数进行了比较,但不幸的是,两种epsilon方法都不能与内部方法完全匹配,但可以达到任意精度。 The bit-shifting method also shows no performance improvement in Chrome over the standard function. 移位方法在Chrome中也没有比标准功能提高任何性能。 So even as far as pointless micro optimization goes this would achieve little. 因此,就无意义的微优化而言,这将收效甚微。

http://jsfiddle.net/J8H8e/1/ http://jsfiddle.net/J8H8e/1/

Number.EPSILON provides the correct answer for X = 1 , but for larger numbers, the largest number n less than one such that (X + n) >> 0 === ceil(X) is based on the exponent of the number. Number.EPSILON为X = 1提供正确的答案,但对于较大的数字,最大的数字n小于1,因此(X + n) >> 0 === ceil(X)基于该数字的指数。 This is based on the way that doubles are structured, with an exponent and a significand. 这是基于具有指数和有效位数的双精度结构的方式。 The precision of the last bit of the significand is based on the exponent, and gives the precision of the number represented. 有效位数的最后一位的精度基于指数,并给出了所表示数字的精度。

Specifically, the number can be computed as follows: 具体来说,可以按以下方式计算数量:

var relEps = Number.EPSILON * ((1 << (((Math.log(X) / Math.LN2) | 0) - 1)) + 1)

After which: 之后:

(X + (1 - relEps)) >> 0 === ceil(X)

I'm pretty sure this is slower than ceil(X) , but it was fun to figure out. 我敢肯定这比ceil(X)慢,但是找出来很有趣。

For something that's actually faster than ceil , this gives a lower bound that shows that 对于实际上比ceil更快的东西,这给出了一个下界,表明

(X + (1 - X * Number.EPSILON)) >> 0

Will work for X !== 0 . 将适用于X !== 0 This is faster than native ceil. 这比本地ceil更快。

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

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