Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
60 views
in Technique[技术] by (71.8m points)

javascript - Getting the significant half of a Number

I'm trying to break a number with value less than or equal to Number.MAX_SAFE_INTEGER into two 32 bit uint values.

My first thought on getting the high value was simply value >>> 32 but this first converts value into a 32b uint and thus the result is 0.

Another thought was to

var high = Number(BigInt(value) >> 32n);

however, going BigInt is relatively slow and I'd like to avoid that if possible

Then I tried Math.floor(value / 2 ** 32) which is way quicker than BigInt and seems accurate but I need a guarantee that it is accurate. Is there any chance of inaccuracy there if the value is between 2 ** 32 and Number.MAX_SAFE_INTEGER? It is a floating point calculation so I am suspicious.

Any other quick ways to get the high value of a 53b integer?

EDIT: If you have a REALLY fast computer, the third approach can be tested

for (let v = 0, high = 0; high <= 2 ** 21; high++) {
    for (let low = 0; low < 2 ** 32; low++) {
        if (Math.trunc(v++ / 2 ** 32) != high) throw "Error at " + v;
    }
}

On my laptop this would take 6 and half years.

question from:https://stackoverflow.com/questions/65923841/getting-the-significant-half-of-a-number

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Extracting the Bits

Given that value is an integer not exceeding Number.MAX_SAFE_INTEGER (253?1) in magnitude, then the low 32 bits of the binary numeral for value can be obtained with:

value % 4294967296

and the high bits can be obtained with:

Math.trunc(value / 4294967296)

(4,294,967,296 is 232. As I do not use JavaScript much, I am not expressing an opinion on the best way to write this in source code. Certainly 4294967296 is correct, but it does not connote the fact that it is 232. (1<<32) might be an option.)

Note that the results obtained this way will be positive (or zero) if value is positive and negative if value is negative. If something different is wanted when value is negative, some adjustment must be made.

Justification

JavaScript is an implementation of ECMAScript. For references here, I use the 2020 specification of ECMA-262.

The % operator on the Number type provides the Number::remainder operation (6.1.6, Table 2), which is specified in 6.1.6.1.6. For the cases at hand (finite dividend and divisor, with divisor non-zero):

… the floating-point remainder r from a dividend n and a divisor d is defined by the mathematical relation r = n - (d × q) where q is an integer that is negative only if n/d is negative and positive only if n/d is positive, and whose magnitude is as large as possible without exceeding the magnitude of the true mathematical quotient of n and d. r is computed and rounded to the nearest representable value using IEEE 754-2019 roundTiesToEven mode.

The text about rounding is superfluous for the remainder operation. Since r cannot be larger in magnitude than the smaller of n or d, it is represented in the Number format at least as finely as each, so the Number format is capable of representing r exactly.

So value % 4294967296 gives us the low 32 bits of value exactly.

In Math.trunc(value / 4294967296), the division is by a power of two. In the Number format, value is represented as f?2e, for some significand f (here including the sign) and some exponent e. Then the mathematical result of value / 4294967296 is f?2e?32. Since value is an integer, e is far from the lower exponent bound of the Number format (?1022), and e?32 is also far from it, so no underflow occurs. That means f?2e?32 is exactly representable, so there is no rounding error in computing value / 4294967296. Then Math.trunc takes the integer portion of this, yielding the high bits of value with no error.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...