【问题标题】:Calculate Square root to decimal places in bash在bash中计算平方根到小数位
【发布时间】:2019-10-22 13:01:20
【问题描述】:

我正在编写一个简单的 bash 脚本,默认情况下计算平方根到小数点后 3 位,但用户可以设置位数……没什么复杂的,我只是从 1 迭代到最小的平方根。由于我的 bash 仍然是基本的,这就是我想出的。

#!/usr/bin/env bash

num=${1}
places=${2-3}
i=0

while [[ $(( i*i )) -lt ${num} ]]    // <= The problem should be here
do
    i=$(( i + 1 ))
done

echo ${i};
rem=$(( num % i ))
root="${i}."
for (( j=0; j<places; j++ ))
do
    rem=$((rem * 10))
    root="$root$((rem / i))"
    rem=$((rem % i))
done
echo ${root}

但由于某种原因,它不会为各种数字产生正确的结果 喜欢bashfile.sh 9 // will produce 3.000 but bashfile.sh 8 will return 3.666,请帮忙,while [[ ]]有什么问题

【问题讨论】:

    标签: bash decimal-point square-root


    【解决方案1】:

    上面的代码尝试通过几个步骤用小数计算 sqrt:

    • 求N的整数部分,存储为I
    • 通过将 R 除以 I 来计算 R=N-I*I 的小数部分。

    但是,这是不正确的。代码假设将 N 分解为 = (II) + (DI),但是要求是找到 N = (D+I)(D+I) = D D + II + 2(D+I)

    两种可能的选择:

    • 将数字乘以 10^(PREC*2),取 sqrt 为整数,然后打印小数点后 PREC 的最后一位数字。
    • 转义到能够处理十进制数字的工具(awk、bc 或 dc)
    • 将小数计算实现为一元搜索

    实施选项 #1:

    PREC=3   # Precision
    V=123456  # input
    for ((i=1 ; i<=PREC ; i++ )) ; do
      V=V*100
    done
    # Loop for matching i as above
    

    【讨论】:

      【解决方案2】:

      这是一个相当简单但不是很有效的解决方案:

      #!/bin/bash
      
      num=$1
      prec=${2:-3}
      
      for (( i=0; i < prec; ++i )); do let num*=100; done
      
      for (( sqrt=0; sqrt*sqrt <= num; ++sqrt )); do :; done
      let --sqrt
      
      sqrt="${sqrt:0:-prec}.${sqrt: -prec}"
      echo $sqrt
      

      为了回答您的问题(“while [[ ]] 有什么问题”),您的比较略有错误。而不是-lt(即&lt;),它应该是&lt;=。并且您需要在循环之后从 i 中减去 1 以获得平方根的正确部分。

      我无法理解计算小数位的代码的第二部分。但是,一个简单的解决方案是改为预乘原始数字以获得所需的精度,这就是我在上面所做的。


      更新

      正如@dash-o 所指出的,如果您使用的是 bash,那么您可能已经安装了 bc 或 awk,它们更适合这个:

      num=$1
      prec=${2:-3}
      
      # using bc
      echo "scale=$prec; sqrt($num)" | bc
      
      # using awk
      awk "BEGIN {printf \"%.${prec}f\n\", sqrt($num)}"
      

      【讨论】:

      • @AderemiDayo 我也注意到了。这似乎是第一个 for 循环。如果你只使用整数,你可以尝试追加 0 而不是乘法。
      • 这是第二个for循环,如果你提供8的精度,它将循环num*10000000000000000次,我什至不知道从哪里开始计算大O...大声笑
      • @AderemiDayo 哦,你是对的。在那种情况下,而不是 ++ 增量,也许尝试使用二进制搜索。为简单起见,您可以假设 num 为上限,然后继续将其切成两半直到得到结果。
      猜你喜欢
      • 1970-01-01
      • 2021-08-03
      • 1970-01-01
      • 1970-01-01
      • 2012-09-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-04-30
      相关资源
      最近更新 更多