MATLAB中整数矩阵的乘法

6

如何在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。


2
当我发现这一点时,我也感到惊讶(和恼怒)。很遗憾,在Matlab中无法正确地进行整数乘法。 - Luis Mendo
1
在处理较小的整数类型时,存在整数溢出的危险,这通常是处理整数时的一部分。然而,MATLAB有时候过于照顾你了。我怀疑他们想在让mtimes处理uint8之前实现某种警告或溢出检测。 - chappjc
有趣的观点@chappjc。我猜IEEE浮点数自然地已经提供了这种保证。看起来,Python等效的numpy在这个问题上会悄无声息地出错。 - MRocklin
@MRocklin:numpy在这种情况下是否允许MATLAB不允许的操作?“errs silently”是什么意思? - Nike
2个回答

5
在这种简单情况下,你可以使用以下方法。
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)

...或者使用bsxfun在一行中完成!请查看更新的答案。 - Luis Mendo
我最喜欢的是最后一个答案——转换为double。如果这样做也是最安全的!+1 - chappjc
1
我知道这是一个旧帖子,所以我发表评论纯粹是为了完整性,因为我遇到了同样的问题。在bsxfun解决方案中,需要为“sum”函数使用“native”标志,否则“sum”会自动返回“double”。 - M.G.
1
@July 你说得对。这是“squeeze”未从矩阵中删除前导单例维度的常见问题。也已经进行了更正,再次感谢! - Luis Mendo
显示剩余9条评论

1
  • MATLAB does not support integer matrix-matrix multiplication due to the lack of industrial support.

    MATLAB uses BLAS (more specifically, Intel's implementation of BLAS, i.e. MKL) to do matrix multiplication. At present, BLAS does not natively support multiplication of integer matrices. However, a good news is that MKL 2018 adds initial support for integer matrices. (cf. this slides)

  • As for your question, if you aim at performance and your matrices are not too small, sum(x.*x) is inferior to int64(double(x)*double(x.')).

  • Use native only when you are sure that overflow and underflow will not happen.

    One extra note is that although native flag can keep the type of return value the same as that of input value. It may suffer from integer overflow or underflow. Check with the following snippet.

    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)
    

    Although single and double can also overflows and underflows, they happens less frequently.


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接