【问题标题】:Multiplication of integer-valued matrices in MATLABMATLAB中整数值矩阵的乘法
【发布时间】:2013-10-25 16:03:14
【问题描述】:

在 MATLAB 中乘以整数值矩阵的最佳方法是什么?

得知以下行为不被接受,我感到很惊讶:

>> x = int64([1, 2])
>> x * x'
Error using  * 
MTIMES is not fully supported for integer classes. At least one input must be scalar.
To compute elementwise TIMES, use TIMES (.*) instead.

我总是可以转换成双倍然后再转换回来。这是最好的解决方案吗?我正在使用 R2013b。

【问题讨论】:

  • 当我发现这一点时,我也很惊讶(也很生气)。很遗憾你不能在 Matlab 中正确地乘以整数
  • integer overflow 存在较小的整数类型的危险,这通常只是处理整数的一部分。但是,MATLAB 有时喜欢牵你的手。我怀疑他们想在让mtimes 处理uint8 之前实施某种警告或溢出检测。
  • 有趣点@chappjc。我猜IEEE浮点自然已经给出了这个保证。看起来 numpy,Python 的等价物,在这个问题上默默地犯了错误。
  • @MRocklin:在这种情况下,numpy 是否允许 MATLAB 不允许的内容? “默默地犯错”是什么意思?

标签: matlab matrix matrix-multiplication


【解决方案1】:

在这种简单的情况下,您可以使用 using 来解决问题

sum(x.*x)

似乎整数矩阵正确支持times (.*),但不支持mtimes (*)。

对于一般矩阵乘法:让AB 成为两个大小合适的矩阵,这样A*B 就存在。由于整数支持timessum,您可以推广上述技巧,使用bsxfunsum 计算乘积矩阵的所有项,如下所示。

编辑:正如@July 所述,您需要sum 中的'native' 标志才能保留整数类型的结果。也感谢您指出由squeeze 引起的问题,现在通过使用第二个permute 更正。

permute(sum(bsxfun(@times, A.', permute(B, [1 3 2])), 1, 'native'), [2 3 1])

例如:

>> A = int64([1 2; 3 4])
A =
                    1                    2
                    3                    4
>> B = int64([5 7 9; 6 8 10])
B =
                    5                    7                    9
                    6                    8                   10
>> permute(sum(bsxfun(@times, A.', permute(B, [1 3 2])), 'native'), [2 3 1])
ans =
    17    23    29
    39    53    67

无论如何,最快的选择似乎是double(A)*double(B)

【讨论】:

  • 不错的提示。我的实际应用程序比我发布的示例更复杂。我想做一个完整的矩阵矩阵乘法。
  • 那么您似乎需要两个循环(嵌套)来使用sum(x(ii,:).*y(:,jj).') 计算产品矩阵的每个条目。转换为double(或single)可能更快
  • 我知道这是一篇旧帖子,所以我发布我的评论纯粹是为了完整起见,因为我遇到了同样的问题。在 bsxfun 解决方案中,'sum' 函数需要使用 'native' 标志,否则 'sum' 会自动返回 'double'。
  • @July 你是对的。这是squeeze 不从矩阵中删除前导单例维度的常见问题。也更正了,再次感谢!
【解决方案2】:
  • 由于缺乏工业支持,MATLAB 不支持整数矩阵-矩阵乘法。

    MATLAB 使用 BLAS(更具体地说,英特尔的 BLAS 实现,即 MKL)来进行矩阵乘法。目前,BLAS 本身并不支持整数矩阵的乘法。然而,一个好消息是 MKL 2018 增加了对整数矩阵的初始支持。 (参见this slides

  • 至于你的问题,如果你的目标是性能并且你的矩阵不是太小,sum(x.*x)不如int64(double(x)*double(x.'))

  • 只有在确定不会发生上溢和下溢时才使用native

    另外需要注意的是,虽然native 标志可以保持返回值的类型与输入值的类型相同。它可能会遭受整数上溢或下溢。检查以下 sn-p。

    sum(int8(-ones(300,1)), 'native') % ans = -128 (of type int8)
    sum(int8(ones(300,1)), 'native')  % ans = 127  (of type int8)
    sum(int8(ones(300,1)))            % ans = 300  (of type double)
    

    虽然singledouble 也可以上溢和下溢,但它们发生的频率较低。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-04-09
    • 1970-01-01
    • 2013-11-29
    • 2012-01-09
    • 2012-11-23
    • 2011-11-30
    相关资源
    最近更新 更多