首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >添加锈蚀和组件

添加锈蚀和组件
EN

Stack Overflow用户
提问于 2021-09-03 20:11:27
回答 1查看 231关注 0票数 1

给出了,我想把级数1,2,3的前n项和起来。具有以下功能的Rust

代码语言:javascript
复制
fn sum_sequence(x: u64) -> u64 
{
    let mut s: u64 = 0;

    for n in 1..=x
    {
        s = s + n;
    }
    return s;
}

为x64体系结构编译它时

代码语言:javascript
复制
cargo build --release

然后用x=10000000000运行它,结果是13106511857580896768 -罚款。

当我将这个函数编译成组件时,但是

代码语言:javascript
复制
cargo build --target wasm32-unknown-unknown --release

并使用与前面相同的参数运行它,x=10000000000

代码语言:javascript
复制
wasmtime ./target/wasm32-unknown-unknown/release/sum_it.wasm --invoke sum_sequence 1000000000

然后,结果是-5340232216128654848

我不会期望在Rust被编译到x64与Rust被编译到WASM之间的结果有任何偏差。此外,从WASM文本文件(下面),我不明白为什么我应该得到一个负面的结果,当我运行它与WASM。

为什么WASM显示了不同的结果,我能做什么来纠正WASM的计算?

代码语言:javascript
复制
(module
  (type (;0;) (func (param i64) (result i64)))
  (func $sum_sequence (type 0) (param i64) (result i64)
    (local i64 i64 i32)
    block  ;; label = @1
      local.get 0
      i64.eqz
      i32.eqz
      br_if 0 (;@1;)
      i64.const 0
      return
    end
    i64.const 1
    local.set 1
    i64.const 0
    local.set 2
    block  ;; label = @1
      loop  ;; label = @2
        local.get 1
        local.get 2
        i64.add
        local.set 2
        local.get 1
        local.get 1
        local.get 0
        i64.lt_u
        local.tee 3
        i64.extend_i32_u
        i64.add
        local.tee 1
        local.get 0
        i64.gt_u
        br_if 1 (;@1;)
        local.get 3
        br_if 0 (;@2;)
      end
    end
    local.get 2)
  (table (;0;) 1 1 funcref)
  (memory (;0;) 16)
  (global (;0;) (mut i32) (i32.const 1048576))
  (global (;1;) i32 (i32.const 1048576))
  (global (;2;) i32 (i32.const 1048576))
  (export "memory" (memory 0))
  (export "sum" (func $sum))
  (export "__data_end" (global 1))
  (export "__heap_base" (global 2)))
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-09-03 20:25:31

这似乎是因为wasm不支持本地u64作为类型,只支持签名的变体(特别是i64),这就是为什么它使用i64作为算术操作的类型。因为这会溢出一个64位整数(正确的输出是n * (n+1) / 2,或50000000005000000000 ),您将得到一个负值,这是由于溢出,然后打印到控制台。这是因为在wasm中缺乏类型支持。

仅供参考,我从这里开始使用一个Σ n=0 to N := (N * (N+1) / 2,因为它在计算上要快得多,而且为了我们的目的,它是正确的。

结果,50000000005000000000占用内存中的65.4位来精确地在内存中表示,这就是为什么您获得了x86_64和wasm的包装行为,这正是它包装的类型不同的原因。

使用NumPy,我们可以清楚地确认这一点:

代码语言:javascript
复制
>>> import numpy as np
>>> a = np.uint64(10000000000)
>>> b = np.uint64(10000000001)
>>> (a >> np.uint64(1)) * b
13106511857580896768

>>> import numpy as np
>>> a = np.int64(10000000000)
>>> b = np.int64(10000000001)
>>> (a >> np.int64(1)) * b
-5340232216128654848

您所获得的值是由于无符号和有符号(两个补码)整数溢出造成的。(注意:我使用一个右位移位来模拟除以二,我可能也可以使用//操作符)。

编辑:另外,在Herohtar的评论中也提出了一个很好的观点:如果在调试模式下运行,它显然会溢出,对'attempt to add with overflow'感到恐慌。

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/69050143

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档