How to achieve the output with binary operators?

63 views Asked by At

I have three variables and trying to get the result using only binary operators. But somehow it does not work.

This does not work:

const var1 = 0x4C44
const var2 = 3
const var3 = 1

const result = (var1 << 32) + (var2 << 16) + var3

console.log(result.toString(16))

This is what I try to get:

const var1 = 0x4C44
const var2 = 3
const var3 = 1

const result = 0x4C4400030001

console.log(result.toString(16))

can anyone please point me in the right direction?

2

There are 2 answers

4
Andrew Parks On BEST ANSWER

The << operator converts the number into a signed 32-bit integer. See https://262.ecma-international.org/9.0/#sec-left-shift-operator

This means you get an overflow and strange results when you shift your number beyond 2^31.

console.log(0x4C44 << 19)   //  1646264320
console.log(0x4C44 << 20)   // -1002438656

console.log((2**31)-1 << 0) //  2147483647
console.log((2**31)   << 0) // -2147483648

Use Javascript bigints instead (ECMAscript 2020 onwards):

const var1 = 0x4C44n
const var2 = 3n
const var3 = 1n

const result = (var1 << 32n) + (var2 << 16n) + var3

console.log(result.toString(16))

1
André Fiedler On

Thanks again to @Andrew Parks

I wrote a small test script and executed it on the target embedded system (NXP i.MX6 SoM / ARM Cortex-A9 i.MX6DL Dual-Core Lite @ 1GHz) running Node.js v16.14.2

const { performance, PerformanceObserver } = require('node:perf_hooks')

function test1() {
    for (let i = 0; i < 1000000; i++) {
        const var1 = 0x4C44
        const var2 = 3
        const var3 = 1

        const val = var1.toString(16) + '000' + var2 + '000' + var3

        const buf = Buffer.from(val, 'hex')
    }
}

function test2() {
    for (let i = 0; i < 1000000; i++) {
        const var1 = 0x4C44
        const var2 = 3
        const var3 = 1

        const val = (BigInt(var1) << 48n) + (BigInt(var2) << 32n) + (BigInt(var3) << 16n)

        const buf = Buffer.alloc(8)
        buf.writeBigInt64BE(val, 0)
    }
}

const wrapped1 = performance.timerify(test1)
const wrapped2 = performance.timerify(test2)

const obs = new PerformanceObserver((list) => {
    console.log('using string operations: ' + list.getEntries()[0].duration)
    console.log('using big int and binary operations: ' + list.getEntries()[1].duration)

    performance.clearMarks()
    performance.clearMeasures()
    obs.disconnect()
})
obs.observe({ entryTypes: ['function'] })

wrapped1()
wrapped2()
# run 1
using string operations: 6254.104259001091
using big int and binary operations: 5737.1327509991825

# run 2
using string operations: 6202.929297998548
using big int and binary operations: 5627.462751999497

# run 3
using string operations: 6260.041892001405
using big int and binary operations: 5640.075751001015