Bash - 乘法二维矩阵

标签 bash matrix

假设我有二维矩阵 n x n,并且我们已经知道 n=4 和值 1 - 16,如 this

我必须乘以这样的部分:

Array1*Array2 = 结果

Array3*res​​ult = result1

Array4*result1 = result2

ShowMatrix()
{
echo "MyMatrix is:"
for((i=0;i<$n;i++))do
   for((j=0;j<$n;j++))do
printf '  '${myArray[i*n+j]}
done
printf '\n';
done
}

我试着像模式一样将它分成 4 个部分,并将每个部分分配给 Array1、Array2、Array3 和 Array4

cut1()
{
for((i=0;i<$n/2;i++))do
   for((j=0;j<$n/2;j++))do
Array1[i*n+j]=${myArray[i*n+j]}
done
done
}

cut2()
{
for((i=0;i<$n/2;i++))do
   for((j=$n/2;j<$n;j++))do
Array2[i*n+j]=${myArray[i*n+j]}
done
done
}

cut3()
{
for((i=$n/2;i<$n;i++))do
   for((j=0;j<$n/2;j++))do
Array3[i*n+j]=${myArray[i*n+j]}
done
done
}

cut4()
{
for((i=$n/2;i<$n;i++))do
   for((j=$n/2;j<$n;j++))do
Array4[i*n+j]=${myArray[i*n+j]}
done
done
}

在那之后,我尝试像在架构中那样将它们相乘:

Array1*Array2 = 结果

Array3*res​​ult = result1

Array4*result1 = result2

multiply()
{
 for((i=0;i<$n;i++))do
   for((j=0;j<$n;j++))do
     result[i*n+j]=0
     for((k=0;k<$n;k++))do
let "result[i*n+j]=${result[i*n+j]}+${Array1[i*n+k]}*${Array2[k*n+j]}"
done
done
done
}

multiply1()
{
 for((i=0;i<$n;i++))do
   for((j=0;j<$n;j++))do
     result1[i*n+j]=0
     for((k=0;k<$n;k++))do
let "result1[i*n+j]=${result1[i*n+j]}+${result[i*n+k]}*${Array3[k*n+j]}"
done
done
done
}

multiply2()
{
 for((i=0;i<$n;i++))do
   for((j=0;j<$n;j++))do
     result2[i*n+j]=0
     for((k=0;k<$n;k++))do
let "result2[i*n+j]=${result2[i*n+j]}+${result1[i*n+k]}*${Array4[k*n+j]}"
done
done
done
}

调用函数后的结果:

cut1
cut2
cut3
cut4
multiply
multiply1
multiply2


echo "result is:"
for((i=0;i<$n;i++))do
   for((j=0;j<$n;j++))do
printf '  '${result[i*n+j]}
done
printf '\n';
done

echo "result1 is:"
for((i=0;i<$n;i++))do
   for((j=0;j<$n;j++))do
printf '  '${result1[i*n+j]}
done
printf '\n';
done

echo "result2 is:"
for((i=0;i<$n;i++))do
   for((j=0;j<$n;j++))do
printf '  '${result2[i*n+j]}
done
printf '\n';
done

最佳答案

所写代码的主要概念问题是,您将一个大数组分成较小的部分,但没有针对这些部分的缩小尺寸进行调整。

具体来说,cut 函数中有一个明显的错误。当存储回 Array1..Array3 时,您使用的是较大数组的索引,而不是缩减数组。 POSIX shell 和 bash 愉快地扩展缺失的条目并用零填充它们。所以 bash 不会帮助你在这里找到你的错误。

同样,multiply 函数应该只尝试在缩小数组的边界上乘以。通过将二维数组存储为线性数组,获取数组的边有点麻烦:要么像我下面那样传递维度,要么从数组中获取大小(假设已正确初始化)并取平方根。

您提到您认为是随机行为。我怀疑这里发生的事情是从您的环境或过去的执行中查找的动态变量正在将值提供给各种子例程。为了防止这种情况,我会在函数内声明所有局部变量。当然,有些数组不是本地的,但同样,在程序中您也应该声明它们。

这就是为什么我认为其他人建议您使用更合适的语言来做这样的事情。我同意这些评估。

但如果您确实必须使用 POSIX shell,您可能应该更好地了解和使用它。您可以使用 bash -n 检查代码的语法。如果代码是 POSIX 兼容的(我在此强烈推荐),那么 ksh -n 将为您提供对该程序的更全面和详细的评论。

为了帮助您找到此类程序中的错误,我建议 the bash debugger .为了测试代码,我建议使用 Kate Ward 的单元测试程序 shunit .

我重写了修复错误的代码。据我所知,它遵循你所说的你想做的和你拥有的代码。但是,您从未真正描述过您正在尝试做什么,也没有对您拥有的特定数据给出预期的答案,所以我没有办法独立检查事情。

下面我建议做但没有做的一件事是 DRY(不要重复自己)代码。如果您传递开始点和结束点以及要存储结果的数组的名称,则 4 个 cut 函数可以折叠成一个例程。不过我认为您必须在这里使用 eval .

同样,通过传入要处理的数组的名称,可以将 3 个乘法 函数合并为一个。

我通过增强您的 ShowMatrix 例程删除了重复的数组显示代码。

typeset -ir n=4
typeset -a Array=()
typeset -a Array1=()
typeset -a Array2=()
typeset -a Array3=()
typeset -a Array4=()
typeset -a Result=()
typeset -a Result1=()
typeset -a Result2=()


ShowMatrix() {
    typeset arr=$1
    typeset n=$2
    typeset -i i
    echo "Matrix $arr is:"
    for ((i=0;i<n;i++)) ; do
        typeset -i j
        typeset -i val
        for ((j=0;j<n;j++)) ; do
            ((val=${arr}[i*n+j]))
            printf '%5d ' $val
        done
        printf '\n';
    done
}

cut1() {
    typeset -i i
    typeset -i k=0
    for((i=0;i<n/2;i++)) ; do
        typeset -i j
        for((j=0;j<n/2;j++)); do
            ((Array1[k++] = Array[i*n+j]))
        done
    done
}

cut2() {
    typeset -i i
    typeset -i k=0
    for((i=0;i<n/2;i++)) ; do
        typeset -i j
        for((j=n/2;j<n;j++)) ; do
            ((Array2[k++] = Array[i*n+j]))
        done
    done
}

cut3() {
    typeset -i i
    typeset -i k=0
    for((i=n/2;i<n;i++)) ; do
        for((j=0;j<n/2;j++)) ; do
            ((Array3[k++] = Array[i*n+j]))
        done
    done
}

cut4() {
    typeset -i i
    typeset -i k=0
    for((i=n/2;i<n;i++)) ; do
        for((j=n/2;j<n;j++));  do
           ((Array4[k++] = Array[i*n+j]))
        done
    done
}

multiply() {
    typeset -i i
    typeset -i n=$1
    ShowMatrix Array1 $n
    ShowMatrix Array2 $n
    for((i=0;i<n;i++)); do
        typeset -i j
        for((j=0; j < n; j++)); do
            typeset -i l
            ((l=i*n+j))
            ((Result[l]=0))
            typeset -i k
            for((k=0; k<n; k++)) ; do
                    ((Result[l] += Array1[i*n+k]*Array2[k*n+j]))
            done
        done
    done
}

multiply1()
{
    typeset -i n=$1
    ShowMatrix Result $n
    ShowMatrix Array3 $n
    typeset -i i
    for((i=0; i < n; i++)) ; do
        typeset -i j
        for((j=0; j < n; j++)); do
            typeset -i l
            ((l=i*n+j))
            ((Result1[i*n+j]=0))
            typeset -i k
            for ((k=0;k<n;k++));  do
                ((Result1[l] += Result[i*n+k]*Array3[k*n+j]))
            done
        done
    done
}

multiply2() {
    typeset -i i
    typeset -i n=$1
    ShowMatrix Result1 $n
    ShowMatrix Array4 $n
    for ((i=0; i<n; i++)) ; do
        typeset -i j
        for ((j=0; j < n; j++)) ; do
            typeset -i l
            ((l=i*n+j))
            ((Result2[i*n+j]=0))
            typeset -i k
            for((k=0;k<n;k++)); do
                ((Result2[l] += Result1[i*n+k]*Array4[k*n+j]))
            done
        done
    done
}


typeset -i i
for((i=0; i<n*n; i++)) ; do
       ((Array[i]=i+1))
done

cut1
cut2
cut3
cut4

typeset -i n2
((n2 = n / 2))

multiply $n2
multiply1 $n2
multiply2 $n2
ShowMatrix Result2 $n2

关于Bash - 乘法二维矩阵,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27869574/

相关文章:

javascript - 在多维数组中拼接奇数/偶数但结果一两个奇数/数字炫耀

通过 LED 矩阵和按钮控制开和关

python - 添加具有不同标签和不同维度的矩阵

sql - 从 bash 创建 postgresql 时出错 - 安装和导入

java - Scala 检查外部进程 ID (pid) 当前是否正在运行?

bash - 函数中的源文件采用函数参数

java - 类未找到 : VMDisconnectedException) after losing . bashrc

从字符串创建自定义矩阵

c - 从文本文件中读取并放入多二维数组中

linux - 防止 Gnome 终端在执行后退出