【问题标题】:More simple math help in bash!bash 中更简单的数学帮助!
【发布时间】:2010-12-24 08:16:51
【问题描述】:

在与this question 相同的线程中,我再试一次,并要求 SO 帮助解决我应该如何处理这个问题。我正在编写一个需要执行以下操作的 bash 脚本:

  1. 我在xy 中有一个圆,半径为r
  2. 我指定resolution,这是我正在检查的点之间的距离。
  3. 我需要遍历 x 和 y(从 -r 到 r)并检查当前 (x,y) 是否在圆圈中,但我需要遍历离散的 ij
  4. 那么ij需要从-r/resolution转到+r/resolution
  5. 在循环中,需要发生的是echo "some_text i*resolution j*resolution 15.95 cm"(注意缺少$,因为我一无所知)。这个输出是我真正想要的。

迄今为止我最好的一击:

r=40.5
resolution=2.5
end=$(echo "scale=0;$r/$resolution") | bc

for (( i=-end; i<=end; i++ ));do
    for (( j=-end; j<=end; j++ ));do
        x=$(echo "scale=5;$i*$resolution") | bc
        y=$(echo "scale=5;$j*$resolution") | bc
        if (( x*x + y*y <= r*r ));then      <-- No, r*r will not work
            echo "some_text i*resolution j*resolution 15.95 cm"
        fi
    done
done 

我已经受够了 bash,可能会像我上一个问题中有人建议的那样研究 ksh,但如果有人知道执行此操作的正确方法,请告诉我!无论如何解决这个问题,它肯定会让我未来的气质转向 bash 脚本。

【问题讨论】:

  • 感谢您的帮助;我会在早上几个小时回来更新和回复。
  • ksh ?拜托……情况越来越糟了。我的观点是你使用了错误的工具。 shell 应该是用来运行程序的,而不是用来做数学的。
  • 我有项目负责人坚持以前所有事情都必须在 shell 中完成,因为“没有人知道 perl”。有时,你只需要让它在你被给予的约束下工作。即使这些限制条件不健全。
  • 另一方面,例如,如果您被要求在汇编程序中生成代码,这看起来像是一个疯狂的约束,但这可能有一个动机背景(与以前的代码集成、时序问题)。这很疯狂,因为不常见,要求很高,很难测试,也很难做到,但在这种情况下,这并不是不合理或没有动力的。我同意,人为因素确实存在,并且必须予以充分考虑,但这始终是一个平衡问题。一个好的经理应该知道什么时候改进他的团队的技术,否则他会停留在旧的技术中。
  • 如果人们坚持你使用 shell 做数学,我会挖出 dc.sed 并说“你是什么意思,你不知道 sed”? sed.sourceforge.net/grabbag/scripts/dc.sed

标签: bash syntax math


【解决方案1】:

您可能希望将管道包含在 $() 中的 bc 中。而不是。

end=$(echo "scale=0;$r/$resolution") | bc

使用

end=$(echo "scale=0;$r/$resolution" | bc)

应该会有所帮助。

编辑这是一个解决方案。

r=40.5
resolution=2.5
end=$(echo "scale=0;$r/$resolution" | bc)

for i in $(seq -${end} ${end}); do
    for j in $(seq -${end} ${end}); do
        x=$(echo "scale=5;$i*$resolution" | bc)
        y=$(echo "scale=5;$j*$resolution" | bc)

        check=$(echo "($x^2+$y^2)<=$r^2" | bc)    
        if [ ${check} -eq '1' ]; then
            iRes=$(echo "$i*$resolution" | bc)
            jRes=$(echo "$j*$resolution" | bc)      
            echo "some_text $iRes $jRes 15.95 cm"
        fi
    done
done

【讨论】:

  • 亚当,最后的回声只打印字面上的“some_text iresolution jresolution 15.95 cm”!
  • 添加了更正,但您可能希望根据您的要求更改 iRes / jRes 方程的比例。
  • 谢谢。在我的 Mac 上,seq 的使用必须替换为 x=-end;x
  • 在 Mac(和其他 BSD?)上,可以使用 jot 命令代替 seq。参数语法有点不同。
【解决方案2】:

你还没有听说过 (g)awk ??。那你应该去了解一下。从长远来看,它将使您受益。将你的 bash 脚本翻译成 awk。

awk 'BEGIN{
    r=40.5
    resol=2.5
    end = r/resol
    print end
    for (i=-end;i<=end;i++) {
        for( j=-end;j<=end;j++ ){
            x=sprintf("%.5d",i*resol)
            y=sprintf("%.5d",j*resol)
            if ( x*x + y*y <= r*r  ){
                print ".......blah blah ......"
            }
        }    
    }
}'

【讨论】:

    【解决方案3】:

    它看起来更像是bc 脚本而不是 Bash 脚本,所以这里是:

    #!/usr/bin/bc -q
    /* -q suppresses a welcome banner - GNU extension? */ 
    r = 40.5
    resolution = 2.5
    
    scale = 0
    end = r / resolution
    
    scale = 5
    
    for ( i = -end; i <= end; i++ ) {
        /* moved x outside the j loop since it only changes with i */
        x = i * resolution
        for ( j = -end; j <= end; j++ ) {
            y = j * resolution
            if ( x^2 * y^2 <= r^2 ) {
                /*
                   the next few lines output on separate lines, the quote on 
                   a line by itself causes a newline to be created in the output
                   numeric output includes newlines automatically
                   you can comment this out and uncomment the print statement
                   to use it which is a GNU extension
                */
                /* */
                "some_text
    "
                i * resolution
                j * resolution
                "15.95 cm
    "
                /* */
                /* non-POSIX: 
                print "some_text ", i * resolution, " ", j * resolution, " 15.95 cm\n"
                */
            }
        }
    }
    quit
    

    【讨论】:

      【解决方案4】:

      如前所述,这个问题可能最好使用 bc、awk、ksh 或其他脚本语言来解决。

      Pure Bash。 实际上需要浮点运算的简单问题有时可以转换为仅使用整数的某种定点运算。以下解决方案模拟小数点后 2 位小数。 如果这个精度足够的话,循环内部就不需要管道和外部进程。

      factor=100                                      # 2 digits after the decimal point
      r=4050                                          # the representation of 40.50
      resolution=250                                  # the representation of  2.50
      end=$(( (r/resolution)*factor ))                # correct the result of the division
      
      for (( i=-end; i<=end; i+=factor )); do
          for (( j=-end; j<=end; j+=factor )); do
              x=$(( (i*resolution)/factor ))          # correct the result of the division
              y=$(( (j*resolution)/factor ))          # correct the result of the division 
              if [ $(( x*x + y*y )) -le $(( r*r )) ] ;then     # no correction needed
                              echo "$x $y ... "
              fi
          done
      done
      
      echo -e "resolution = $((resolution/factor)).$((resolution%factor))"
      echo -e "r          = $((r/factor)).$((r%factor))"
      

      【讨论】:

      • 我写的脚本实际依赖于用户指定的单位,所以我想如果我指定纳米,这实际上可以很好地工作!
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-07-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多