JavaScript支持64位整数吗?

ahm*_*md0 76 javascript 64-bit integer numbers

我有以下代码:

var str = "0x4000000000000000";   //4611686018427387904 decimal
var val = parseInt(str);
alert(val);
Run Code Online (Sandbox Code Playgroud)

我得到这个值:" 4611686018427388000",这是0x4000000000000060

我想知道JavaScript是否错误处理64位整数还是我做错了什么?

nnn*_*nnn 82

JavaScript表示使用IEEE-754双精度(64位)格式的数字.据我所知,这给你53位精度,或十五到十六位小数.您的号码比JavaScript可以处理的数字更多,因此您最终得到一个近似值.

这并不是真正"错误处理",但显然如果你需要对大数字进行全面精确,它并没有多大帮助.有一些JS库可以处理更大的数字,例如BigNumberInt64.

  • 应该补充说,位级操作仅限于32位IIUC. (33认同)
  • ([@Michaelangelo]评论(http://stackoverflow.com/users/1339447/michaelangelo))不幸的是,[ECMAScript 2015规范](http://www.ecma-international.org/ecma-262/6.0/ )(版本6)没有官方支持`UInt64`; 虽然Mozilla已经添加了对[UInt64](https://developer.mozilla.org/en-US/docs/Mozilla/js-ctypes/js-ctypes_reference/UInt64)的支持 - 但这是非标准的.WebGL有类似的需求,但不幸的是,也没有"Uint64Array",只有[Uint32Array](https://www.khronos.org/registry/typedarray/specs/latest/#7). (3认同)
  • 关闭goog.math.Long也可能有所帮助:http://docs.closure-library.googlecode.com/git/class_goog_math_Long.html (2认同)
  • goog.math.Long文档已经移动:http://google.github.io/closure-library/api/class_goog_math_Long.html (2认同)
  • goog.math.Long文档再次移动:https://google.github.io/closure-library/api/goog.math.Long.html(谢谢,@ Passrier) (2认同)

Shn*_*sel 10

Chromium 57版和更高版本本机支持任意精度整数。这称为BigInt,其他浏览器也正在使用它。它比JavaScript实现快得多

  • @CiboFATA8:他正在谈论 BigInt 作为本机浏览器组件与在 JavaScript 中实现的 BigInt。您正在将 js 数字(精度约为 53 位(不是 64 位)的浮点数)与本机浏览器 BigInt(也不是 64 位)进行比较。 (5认同)

sma*_*ipt 10

即,V8 JavaScript 是 Smalltalk 的衍生引擎。(20 世纪 80 年代至今)Lisp 和 Smalltalk 引擎支持使用 <LargeInteger>(有时称为 <BigInt>)的多精度算术。剧透一下, Google 的Dart团队主要是一群前 Smalltalkers 将他们的经验整合到 JS 领域。

这些类型的数字具有无限的精度,通常用作构建块来提供 <Rational:Fraction> 对象,其分子和分母可以是任何类型的数字,包括 <BigInt>。有了它,我们就可以表示实数、虚数,并且可以完美精确地表示无理数(如 (1/3))。

注:我是 Smalltalk、JS 和其他语言及其引擎和框架的长期实现者和开发者。

如果对多精度算术进行适当的 <BigInt> 作为 JavaScript 的标准功能,将为一系列巨大的操作打开大门,包括本机高效加密(这对于多精度数字很容易实现)。

例如,在我的 1998 年的 Smalltalk 引擎之一中,在 2.3GHz 的 cpu 上我刚刚运行:

[10000 factorial] millisecondsToRun => 59ms
10000 factorial asString size => 35660 digits

[20000 factorial] millisecondsToRun => 271ms
20000 factorial asString size => 77338 digits
Run Code Online (Sandbox Code Playgroud)

定义为:(说明<BigInt>多精度的实际应用)

factorial

   "Return the factorial of <self>."

   | factorial n |

    (n := self truncate) < 0 ifTrue: [^'negative factorial' throw].
    factorial := 1.
    2 to: n do:
    [:i |
        factorial := factorial * i.
    ].
   ^factorial
Run Code Online (Sandbox Code Playgroud)

Lars Bak(与我同时代)的 V8 引擎源自 David Ungar 的 Animorphic Smalltalk,其 SELF 作品源自 Smalltalk-80,随后演变成 JVM,并由 Lars for Mobile 重做了,后来成为 V8 引擎的基础。

我提到这一点是因为 Animorphic Smalltalk 和 QKS Smalltalk 都支持类型注释,这使得引擎和工具能够以类似于 TypeScript 尝试用于 JavaScript 的方式来推理代码。

该注释提示及其对语言、工具和运行时引擎的使用提供了支持正确支持多精度算术类型提升和强制规则所需的多种方法(而不是双重分派)的能力。

反过来,这又是在一致框架中支持 8/16/32/64 int/uint 和许多其他数字类型的关键。

<Magnitude|Number|UInt64>来自 QKS Smalltalk 1998 的多方法示例

Integer + <Integer> anObject

   "Handle any integer combined with any integer which should normalize
    away any combination of <Boolean|nil>."
   ^self asInteger + anObject asInteger

-- multi-method examples --

Integer + <Number> anObject

   "In our generic form, we normalize the receiver in case we are a
    <Boolean> or <nil>."
   ^self asInteger + anObject

-- FFI JIT and Marshaling to/from <UInt64>

UInt64 ffiMarshallFromFFV
   |flags| := __ffiFlags(). 
   |stackRetrieveLoc| := __ffiVoidRef().
    ""stdout.printf('`n%s [%x]@[%x] <%s>',thisMethod,flags,stackRetrieveLoc, __ffiIndirections()).
    if (flags & kFFI_isOutArg) [
        "" We should handle [Out],*,DIM[] cases here
        "" -----------------------------------------
        "" Is this a callout-ret-val or a callback-arg-val
        "" Is this a UInt64-by-ref or a UInt64-by-val
        "" Is this an [Out] or [InOut] callback-arg-val that needs 
        ""   to be updated when the callback returns, if so allocate callback
        ""   block to invoke for doing this on return, register it as a cleanup hook.
    ].
   ^(stackRetrieveLoc.uint32At(4) << 32) | stackRetrieveLoc.uint32At(0).

-- <Fraction> --

Fraction compareWith: <Real> aRealValue

   "Compare the receiver with the argument and return a result of 0
    if the received <self> is equal, -1 if less than, or 1 if
    greater than the argument <anObject>."
   ^(numerator * aRealValue denominator) compareWith:
            (denominator * aRealValue numerator)

Fraction compareWith: <Float> aRealValue

   "Compare the receiver with the argument and return a result of 0
    if the received <self> is equal, -1 if less than, or 1 if
    greater than the argument <anObject>."
   ^self asFloat compareWith: aRealValue

-- <Float> --

Float GetIntegralExpAndMantissaForBase(<[out]> mantissa, <const> radix, <const> mantissa_precision)
   |exp2| := GetRadix2ExpAndMantissa(&mantissa).
    if(radix = 2) ^exp2.

   |exp_scale| := 2.0.log(radix).
   |exp_radix| := exp2 * exp_scale.
   |exponent| := exp_radix".truncate".asInteger.
    if ((|exp_delta| := exp_radix - exponent) != 0) [
       |radix_exp_scale_factor| := (radix.asFloat ^^ exp_delta).asFraction.
        "" Limit it to the approximate precision of a floating point number
        if ((|scale_limit| := 53 - mantissa.highBit - radix.highBit) > 0) [
            "" Compute the scaling factor required to preserve a reasonable
            "" number of precision digits affected by the exponent scaling 
            "" roundoff losses. I.e., force mantissa to roughly 52 bits
            "" minus one radix decimal place.
           |mantissa_scale| := (scale_limit * exp_scale).ceiling.asInteger.     
            mantissa_scale timesRepeat: [mantissa :*= radix].
            exponent :-= mantissa_scale.
        ] else [
            "" If at the precision limit of a float, then check the
            "" last decimal place and follow a rounding up rule
            if(exp2 <= -52 and: [(mantissa % radix) >= (radix//2)]) [
                mantissa := (mantissa // radix)+1.
                exponent :+= 1.
            ].
        ].
        "" Scale the mantissa by the exp-delta factor using fractions
        mantissa := (mantissa * radix_exp_scale_factor).asInteger.
    ].

    "" Normalize to remove trailing zeroes as appropriate
    while(mantissa != 0 and: [(mantissa % radix) = 0]) [
        exponent :+= 1.
        mantissa ://= radix.
    ].
   ^exponent.
Run Code Online (Sandbox Code Playgroud)

我预计随着 <BigInt> 的发展,一些类似的模式将开始出现,以支持 UIn64/Int64 和其他结构或数字类型的 JavaScript。