在 bash 中计算平方根到小数位

Calculate Square root to decimal places in bash

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

#!/usr/bin/env bash

num=
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 [[ ]]

有什么问题

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

  • 计算N的整数部分,存为I
  • 用 R 除以 I 计算 R=N-I*I 的小数部分。

但是,这是不正确的。该代码假定将 N 分成 = (II) + (DI),但是,要求是找到 N = (D+I)(D +I) = DD + 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

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

#!/bin/bash

num=
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

为了回答您的问题 ("what is wrong with while [[ ]]"),您的比较稍有不正确。它应该是 <= 而不是 -lt(即 <)。并且您需要在循环后从 i 中减去 1 以获得平方根的正确整数部分。

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


更新

正如@dash-o 所指出的,如果您正在使用 bash,您可能安装了 bc 或 awk,它们更适合于此:

num=
prec=${2:-3}

# using bc
echo "scale=$prec; sqrt($num)" | bc

# using awk
awk "BEGIN {printf \"%.${prec}f\n\", sqrt($num)}"