0

During a calculation, i'm facing a problem on bitwise Left Operator on PHP and JS.

On a certain level/range both php and JS is giving the same output.

For Example: 1<<30 = 1073741824 (Both PHP and JS are right.)

But the problem occurs when i'm trying to move 40.

1<<40;
// php: 1099511627776
// JS:  256

After having study on it , i came to a point that JS can't (or and) can calculate only 32 bit number on bitwise operand.

If there is any procedure, please help. Thanks in advance.

Update: PHP the below function I'm using for convert byte to max possible unit, and was trying to port it into javascript for using inside browser and nodejs.

function formatBytes( $bytes, $args = [] ): array {
    if ( is_string( $args ) ) {
        $args = [ 'flag' => $args ];
    }

    $args  = array_merge( [
        'flag'       => 'Bytes',
        'forStorage' => true,
    ], $args );
    $units = array( 'Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB' );
    $unit  = $args['forStorage'] ? 1024 : 1000;

    if ( 'Bytes' !== $args['flag'] && in_array( $args['flag'], $units, true ) ) {
        $key = array_search( $args['flag'], $units );
        $units = array_slice( $units, $key );
    }

    $bytes = max( $bytes, 0 );
    $pow   = floor( ( $bytes ? log( $bytes ) : 0 ) / log( $unit ) );
    $pow   = min( $pow, count( $units ) - 1 );
    $bytes /= ( 1 << ( 10 * $pow ) );

    return [
       'value' => $bytes,
       'unit'  => $units[ $pow ],
    ];
}

JavaScript Version

function formatBytes(bytes, args = {}) {
    const defaults = {
        'flag': 'Bytes',
        'forStorage': true,
    };
    args = {...defaults, ...args};
    let units = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
    const unit = args.forStorage ? 1024 : 1000;

    if ('Bytes' !== args.flag && units.includes(args.flag)) {
        const key = units.indexOf(args.flag);
        units = units.slice(key, units.length);
    }

    bytes = Math.max(bytes, 0);
    let pow = Math.floor((bytes ? Math.log(bytes) : 0) / Math.log(unit));
    pow = Math.min(pow, units.length - 1);
    bytes /= (1 << (10 * pow));

    return {
        value: bytes,
        unit: units[pow]
    };
}

This works perfectly but until certain limit.

E.G.

// PHP 
print_r( formatBytes( 3114766203813 ) );
// output: Array ( [value] => 2.8328633596293 [unit] => TB )

// JS
console.log( formatBytes(3114766203813) );
// output: {value: 12167055483.644531, unit: 'TB'}

PS: I have modified the JS function to resolve the issue, but curious to learn why this (in the above version of my code) happening and how can i resolve the issue.

  • How far you can shift bits depends on the underlying type of the number you're using. See: [PHP integer types](https://www.php.net/manual/en/language.types.integer.php) and [Javascript number](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#bigint_type). Clearly you have a need for very far shifts and it isn't working. If you tell us what you're actually trying to achieve, and show us your non-working code, we might be able to help. – KIKO Software May 15 '22 at 06:35
  • https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt64Array – mplungjan May 15 '22 at 06:38
  • @KIKOSoftware, Thanks for your feedback. I've updated my question a while ago. Can you please take a look ? – Mehraab Hossain May 25 '22 at 03:09
  • An easy solution would be to change `bytes /= (1 << (10 * pow));` to `bytes /= Math.pow(2, 10 * pow);`. You can also use [BigInt](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt) like this: `bytes /= Number(1n << (10n * BigInt(pow)));`. – KIKO Software May 25 '22 at 07:40
  • @mplungjan You closed this question as being already answered. I think there's a good answer to this question, using [BigInt](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt), which cannot be easily found in your duplicates, see comment above. Could you reopen this question? – KIKO Software May 25 '22 at 07:43
  • @KIKOSoftware From the dupe: https://stackoverflow.com/a/68488096/295783 - I can add any of these https://www.google.com/search?q=javascript+bigint+site+stackoverflow.com+site:stackoverflow.com and you can answer any of them if you wish. If you still want me to re-open this specific question because none of the dupes at SO answers this specific question, then let me know – mplungjan May 25 '22 at 07:56

0 Answers0