BASH:百分比变化 - 如何计算?如何在没有 bc 的情况下获得绝对值?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/27267830/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-18 11:56:15  来源:igfitidea点击:

BASH: Percentage change - how to calculate it? How to get absolute value without bc?

bashmatharithmetic-expressions

提问by dziki

I need to count a percentage change between two values.

我需要计算两个值之间的百分比变化。

The code I have here:

我在这里的代码:

echo $time1
echo $time2
pc=$(( (($time2 - $time1)/$time1 * 100) ))
echo $pc

Brings such output in the console (with set -xeoption)

在控制台中带来这样的输出(带set -xe选项)

+ echo 1800
1800
+ echo 1000
1000
+ pc=0
+ echo 0

The code inside the math expression seems to be written properly, still, I get -80 or so. Why is this happening to me?

数学表达式中的代码似乎写得正确,但我仍然得到 -80 左右。为什么这会发生在我身上?

The second part of the question. I have no access and I will have no access to the bc command. From what I heard it can give me the absolute value of the number I have.

问题的第二部分。我没有访问权限,也无法访问 bc 命令。据我所知,它可以给我所拥有数字的绝对值。

So.. Without the bc command - will this be a good idea for an IF condition?

所以..如果没有 bc 命令 - 这对于 IF 条件是一个好主意吗?

if (( (( "$pc" > 20 || (( "$pc" < -20 )); then...

回答by Tom Fenech

As you have mentioned that it's not necessary to do this in bash, I would recommend using awk:

正如您所提到的,没有必要在 bash 中执行此操作,我建议使用 awk:

awk -v t1="$time1" -v t2="$time2" 'BEGIN{print (t2-t1)/t1 * 100}'

Normally, awk is designed to process files but you can use the BEGINblock to perform calculations without needing to pass any files to it. Shell variables can be passed to it using the -vswitch.

通常,awk 旨在处理文件,但您可以使用该BEGIN块执行计算,而无需向其传递任何文件。可以使用-v开关将外壳变量传递给它。

If you would like the result to be rounded, you can always use printf:

如果您希望结果四舍五入,您可以随时使用printf

awk -v t1="$time1" -v t2="$time2" 'BEGIN{printf "%.0f", (t2-t1)/t1 * 100}'

The %.0fformat specifier causes the result to be rounded to an integer (floating point with 0 decimal places).

%.0f说明符将导致结果格式被舍入为整数(浮点0小数位)。

回答by mirabilos

With correct rounding, nicerwhitespace, and without redundant $signs:

使用正确的四舍五入,更好的空格,并且没有多余的$符号:

pc=$(( ((((time2 - time1) * 1000) / time1) + (time2 > time1 ? 5 : -5)) / 10 ))

回答by mboyar

Maybe you want to prefer bc+awk mixed line, something like this:

也许你想更喜欢 bc+awk 混合线,像这样:

total=70
item=30
percent=$(echo %$(echo "scale = 2; ($item / $total)" | bc -l | awk -F '.' '{print }'))
echo $percent

回答by Stephen Quan

Some notes:

一些注意事项:

  • The math is integer based, so you're getting zero early because you divide
  • The $(( ))syntax will expand variables so use time1instead of $time1
  • The percentage answer is -44 not -80
  • 数学是基于整数的,所以你很早就得到零,因为你除
  • $(( ))语法将扩大变量,这样使用time1的,而不是$time1
  • 百分比答案是 -44 而不是 -80

Here are some examples:

这里有些例子:

echo $(( time2-time1 )) # Output: -800
echo $(( (time2-time1)/time1 )) # Output: 0. see it's already zero!
echo $(( (time2-time1)/time1*100 )) # Output: 0. it's still zero and still 'incorrect'
echo $(( (time2-time1)*100 )) # Output: -80000. fix by multiplying before dividing
echo $(( (time2-time1)*100/time1 )) # Output: -44. this is the 'correct' answer
echo $(( (time2-time1)*100/time2 )) # Output: -80. note this is also an 'incorrect' answer