C++ std::vector 乘法中是不是存在已知的不一致行为?
Posted
技术标签:
【中文标题】C++ std::vector 乘法中是不是存在已知的不一致行为?【英文标题】:Is there a known inconsistent behavior in C++ std::vector multiplication?C++ std::vector 乘法中是否存在已知的不一致行为? 【发布时间】:2017-04-11 17:00:01 【问题描述】:我正在将 Python 代码翻译成 C++。
我在下面的 sn-p 中遇到问题。这两个代码应该是同一个东西,但是它们给了我不同的输出。
我迷路了。错误从k=1
开始。发生了什么,错误在哪里?
如果这很重要:我正在使用 IDE Eclipse Parallel Mars、Windows 10、MinGW 编译 C++ 代码。
Python 3.5:
import numpy as np
a = np.array(([2,-1,0,0],[-1,1.5,-0.5,0],[0,-0.5,0.75,-0.25],[0,0,-0.25,0.25]))
b = np.array(([0,0,0,1]))
for k in range(len(b)-1,-1,-1):
p = 0
print("")
print("k = ", k)
print("b[k] = ", b[k])
for m in range(k+1, len(b)):
print("m = ", m)
print("b[m] = ", b[m])
print("a[k,m] = ",a[k,m])
p += a[k,m] * b[m];
print("p = ", p)
b[k] = (b[k] - p)/a[k,k];
C++11:
#include <iostream>
#include <vector>
int main()
std::vector< std::vector<double> > a = 2,-1,0,0, -1,1.5,-0.5,0,
0,-0.5,0.75,-0.25, 0,0,-0.25,0.25 ;
std::vector<double> b = 0,0,0,1;
double p;
for (int k = b.size()-1; k >= 0; --k)
p = 0;
std::cout << std::endl << "k = " << k << std::endl;
std::cout << "b[k] = " << b[k] << std::endl;
for (size_t m = k+1; m < b.size(); ++m)
std::cout << "m = " << m << std::endl;
std::cout << "b[m] = " << b[m] << std::endl;
std::cout << "a[k][m] = " << a[k][m] << std::endl;
p += a[k][m] * b[m];
std::cout << "p = " << p << std::endl;
b[k] = (b[k] - p)/a[k][k];
return 0;
输出
Python 3.5:
k = 3
b[k] = 1
k = 2
b[k] = 0
m = 3
b[m] = 4
a[k,m] = -0.25
p = -1.0
k = 1
b[k] = 0
m = 2
b[m] = 1
a[k,m] = -0.5
p = -0.5
m = 3
b[m] = 4
a[k,m] = 0.0
p = -0.5
k = 0
b[k] = 0
m = 1
b[m] = 0
a[k,m] = -1.0
p = 0.0
m = 2
b[m] = 1
a[k,m] = 0.0
p = 0.0
m = 3
b[m] = 4
a[k,m] = 0.0
p = 0.0
C++11:
k = 3
b[k] = 1
k = 2
b[k] = 0
m = 3
b[m] = 4
a[k][m] = -0.25
p = -1
k = 1
b[k] = 0
m = 2
b[m] = 1.33333
a[k][m] = -0.5
p = -0.666667
m = 3
b[m] = 4
a[k][m] = 0
p = -0.666667
k = 0
b[k] = 0
m = 1
b[m] = 0.444444
a[k][m] = -1
p = -0.444444
m = 2
b[m] = 1.33333
a[k][m] = 0
p = -0.444444
m = 3
b[m] = 4
a[k][m] = 0
p = -0.444444
【问题讨论】:
在您的 Python 中,b
具有整数 dtype 而不是浮点数。
旁注:reversed(range(0, len(b))
的效率并没有降低,而且似乎更具可读性。
@cdhowie 不在 Python 3+ 中,(b[k] - p)/a[k,k]
将是浮点数。然而,一旦分配给b[k]
,它就会被转换为一个整数,正如 user235711 所暗示的那样。
【参考方案1】:
您的 Python 代码有缺陷。它会截断数字,从而产生整数值,而您期望浮点数带有小数部分。
特别是,np.array(([0,0,0,1]))
正在创建一个具有整数数据类型的 numpy 数组,这意味着当您分配给b[k]
时,浮点值将被截断为整数。从the docs 到numpy.array()
,关于可选的dtype
参数(强调我的):
数组所需的数据类型。如果没有给出,则类型将被确定为在序列中保存对象所需的最小类型。
由于您在输入数组中只提供了整数值,numpy 推断您想要创建一个整数数组。
C++ 代码是正确的。
当我修复您的 Python 代码以在任何地方使用浮点值时,输出与 C++ 版本匹配:
import numpy as np
a = np.array(([2.0,-1.0,0.0,0.0],[-1.0,1.5,-0.5,0.0],[0.0,-0.5,0.75,-0.25],[0.0,0.0,-0.25,0.25]))
b = np.array(([0.0,0.0,0.0,1.0]))
for k in range(len(b)-1,-1,-1):
p = 0
print("")
print("k = ", k)
print("b[k] = ", b[k])
for m in range(k+1, len(b)):
print("m = ", m)
print("b[m] = ", b[m])
print("a[k,m] = ",a[k,m])
p += a[k,m] * b[m];
print("p = ", p)
b[k] = (b[k] - p)/a[k,k];
【讨论】:
【参考方案2】:如果您在创建数组时将dtype
指定为'float64'
b
:
b = np.array(([0,0,0,1]), dtype='float64')
输出如下,与您的 C++ 程序相匹配:
k = 3
b[k] = 1.0
k = 2
b[k] = 0.0
m = 3
b[m] = 4.0
a[k,m] = -0.25
p = -1.0
k = 1
b[k] = 0.0
m = 2
b[m] = 1.3333333333333333
a[k,m] = -0.5
p = -0.66666666666666663
m = 3
b[m] = 4.0
a[k,m] = 0.0
p = -0.66666666666666663
k = 0
b[k] = 0.0
m = 1
b[m] = 0.44444444444444442
a[k,m] = -1.0
p = -0.44444444444444442
m = 2
b[m] = 1.3333333333333333
a[k,m] = 0.0
p = -0.44444444444444442
m = 3
b[m] = 4.0
a[k,m] = 0.0
p = -0.44444444444444442
【讨论】:
以上是关于C++ std::vector 乘法中是不是存在已知的不一致行为?的主要内容,如果未能解决你的问题,请参考以下文章
在 C++ 中检查 std::vector<string> 是不是包含某个值 [重复]
使用 std::vector::swap 方法在 C++ 中交换两个不同的向量是不是安全?
C++ std::vector count统计某个元素个数 是否存在某个值
std::vector 不是 push_back 值到我的向量中吗? C++