我正在尝试在Bash脚本中计算两个图像宽度的商,但是Bash给出了0
作为结果:
RESULT=$(($IMG_WIDTH/$IMG2_WIDTH))
我已经学习了Bash指南,知道应该使用bc
。在网上的所有例子中,他们都使用bc
。在echo
中,我尝试将相同的内容放入我的SCALE
中,但它没有起作用。这是我在教程中找到的例子:
echo "scale=2; ${userinput}" | bc
我该如何让Bash输出一个像 0.5
这样的浮点数?
我正在尝试在Bash脚本中计算两个图像宽度的商,但是Bash给出了0
作为结果:
RESULT=$(($IMG_WIDTH/$IMG2_WIDTH))
我已经学习了Bash指南,知道应该使用bc
。在网上的所有例子中,他们都使用bc
。在echo
中,我尝试将相同的内容放入我的SCALE
中,但它没有起作用。echo "scale=2; ${userinput}" | bc
我该如何让Bash输出一个像 0.5
这样的浮点数?
我知道这个问题很老,但还是有一些诱惑。答案是:你不能... 但你有点可以。让我们尝试这个:
$IMG_WIDTH=1024
$IMG2_WIDTH=2048
$RATIO="$(( IMG_WIDTH / $IMG2_WIDTH )).$(( (IMG_WIDTH * 100 / IMG2_WIDTH) % 100 ))"
IMG_WIDTH=103
和IMG2_WIDTH=100
。 - FedKad虽然在Bash中不能使用浮点数除法,但可以使用定点数除法。您需要做的就是将整数乘以10的某个幂,然后去掉整数部分并使用模运算获取小数部分。根据需要四舍五入。
#!/bin/bash
n=$1
d=$2
# because of rounding this should be 10^{i+1}
# where i is the number of decimal digits wanted
i=4
P=$((10**(i+1)))
Pn=$(($P / 10))
# here we 'fix' the decimal place, divide and round tward zero
t=$(($n * $P / $d + ($n < 0 ? -5 : 5)))
# then we print the number by dividing off the interger part and
# using the modulo operator (after removing the rounding digit) to get the factional part.
printf "%d.%0${i}d\n" $(($t / $P)) $(((t < 0 ? -t : t) / 10 % $Pn))
这并不是真正的浮点数,但如果您想要在一次bc调用中设置多个结果,可以尝试以下方法...
source /dev/stdin <<<$(bc <<< '
d='$1'*3.1415926535897932384626433832795*2
print "d=",d,"\n"
a='$1'*'$1'*3.1415926535897932384626433832795
print "a=",a,"\n"
')
echo bc radius:$1 area:$a diameter:$d
计算半径为 $1$ 的圆的面积和直径
对于那些想要使用已接受的答案计算百分比但丢失精度的人:
如果您运行以下代码:
echo "scale=2; (100/180) * 180" | bc
99.00
,这意味着你失去了精度。echo "result = (100/180) * 180; scale=2; result / 1" | bc -l
现在你获得了99.99
。
因为你只在打印的时候才进行缩放。
请参考这里。
有一些情况下你不能使用 bc,因为它可能不存在,比如在某些简化版的 Busybox 或嵌入式系统中。无论如何,限制外部依赖总是一个好习惯,这样你就可以给被除数(分子)加上零,这相当于乘以10的幂次方(根据需要选择一个10的幂次方),这将使得除法输出一个整数。一旦你获得了这个整数,把它作为字符串处理,并将小数点(从右向左移动)移动与你所乘的10的幂次方相等的次数。这是一个只使用整数来获得浮点结果的简单方法。
计算 1+1
2
calc 1/10
0.1
calc=104348/33215
accuracy=9
calc99p9=$((10**$accuracy))*$calc
result99p9=$((calc99p9))
result=${result99p9: -${#result99p9}: -$accuracy}.${result99p9: -$accuracy}
echo Bash calculated pi to be $result
Bash calculated pi to be 3.141592653
bc
(例如)? - John BollingertimingData.txt
中。首先,我一直小心使用高效的脚本编写方法(项目中提供了详细信息),但我认为真正的关键是您可以在不分叉子shell的情况下运行shellmath
。 shellmath
是一组函数,它们将其结果写入shell变量。另一方面,由于bc
是一个可执行文件,您必须对其进行子shell处理才能捕获结果。 - Clarity_20** 在bash / shell中进行注入安全的浮点数运算 **
注意:本答案的重点是提供在bash(或其他shell)中执行数学运算的注入安全解决方案的想法。当然,同样可以进行高级字符串处理等操作,只需进行微调。
大多数提出的解决方案都会构建小的脚本,使用外部数据(变量、文件、命令行、环境变量)。外部输入可以用于将恶意代码注入引擎中,其中许多方法都有此风险。
以下是使用各种语言执行基本的浮点数计算(结果为浮点数)的比较。它计算A + B * 0.1。
所有解决方案都尝试避免创建动态脚本,这些脚本非常难以维护,而是使用静态程序,并将参数传递到指定的变量中。它们将安全地处理具有特殊字符的参数-减少了代码注入的可能性。例外情况是“BC”,它不提供输入/输出功能。
唯一的例外是“bc”,它不提供任何输入/输出,所有数据都通过stdin传递给程序,并且所有输出都通过stdout进行。所有计算都在沙盒中执行,不允许副作用(打开文件等)。理论上,它是按设计注入安全的!
A=5.2
B=4.3
# Awk: Map variable into awk
# Exit 0 (or just exit) for success, non-zero for error.
#
awk -v A="$A" -v B="$B" 'BEGIN { print A + B * 0.1 ; exit 0}'
# Perl
perl -e '($A,$B) = @ARGV ; print $A + $B * 0.1' "$A" "$B"
# Python 2
python -c 'import sys ; a = float(sys.argv[1]) ; b = float(sys.argv[2]) ; print a+b*0.1' "$A" "$B"
# Python 3
python3 -c 'import sys ; a = float(sys.argv[1]) ; b = float(sys.argv[2]) ; print(a+b*0.1)' "$A" "$B"
# BC
bc <<< "scale=1 ; $A + $B * 0.1"
python3 -c 'import sys ; *a, = map(float, sys.argv[1:]) ; print(a[0] + a[1]*0.1 + a[2])' "$A" "$B"
"4200.0"除数 = 被除数 × 商 + 余数
我们只需要计算商和余数,然后将这些字符串连接在一个变量中。
新的方法仅适用于对数为小数的除数:
function main() {
bar=10030
divisor=100
# divisor=50
quotient=$((bar / divisor))
# remainder=$((bar - v_int * divisor))
remainder=$((bar % divisor))
remainder_init=$remainder
printf "%-15s --> %s\n" "quotient" "$quotient"
printf "%-15s --> %s\n" "remainder" "$remainder"
cnt=0
while :; do
remainder=$((remainder * 10))
aux=$((remainder / divisor))
printf "%-15s --> %s\n" "aux" "$aux"
[[ aux -ne 0 ]] && break
((cnt += 1))
printf "%-15s --> %s\n" "remainder" "$remainder"
done
printf "%-15s --> %s\n" "cnt" "$cnt"
printf "%-15s --> %s\n" "aux" "$aux"
printf $quotient
printf "."
for i in $(seq 1 $cnt); do printf "0"; done
printf $remainder_init
}
clear
main
旧的错误方法:
bar=1234 \
&& divisor=1000 \
&& foo=$(printf "%s.%s" $(( bar / divisor )) $(( bar % divisor ))) \
&& printf "bar is %d miliseconds or %s seconds\n" $bar $foo
输出:bar是1234毫秒或1.234秒