I am just trying to Convert secs back to hours n minutes for a day. However am hitting an error in the Minute Equation! its not evaluating the braces in the order! how can we evalvate math equations like the one I have below.
I want to divide the total_secs by 3600 and then multiply the result with 60 then Again find the modulus of the result with 60.
Here s my attempt
#!/bin/ksh
set -x
total_secs=3685;
hour=$(( (total_secs % 3600) ));
minute=$(( (((total_secs / 3600) * 60) % 60) ));
seconds=$(( (((total_secs / 3600) * (60) * (60)) % 60) ));
echo ""$hour":"$minute":"$seconds""
Thanks In advance
The ordering of operations wasn't what was causing the problem. According to this reference, the Korn shell has the same precedence and associativity as the C programming language, so multiplication, division and remainder happen from left to right. The correct maths would be:
#!/bin/ksh
total_secs=3685
hour=$(( total_secs / 3600 ))
minute=$(( total_secs / 60 % 60 )) # equivalent to (total_secs / 60) % 60
seconds=$(( total_secs % 60 ))
echo "$hour:$minute:$seconds"
# output 1:1:25
If you want to format the output, perhaps you could use printf
printf "%02d:%02d:%02d\n" $hour $minute $seconds
# output 01:01:25
edit: operator precedence
Basic arithmetic operations are carried out in the following order:
* / %
+ -
Multiple operations of the same precedence will be evaluated from left to right as they appear in the expression.
$(( ((x*y) / z) + n ))
is equivalent to either of the following:
$(( x * y / z + n ))
$(( n + x * y / z ))
because in both cases, the * is the highest precedence and nearest to the left of the expression. Second will be the / and finally the +.
There is no harm in inserting additional ( ) to make your intentions clear but remember that the whole expression must be enclosed within $(( )).
Related
lets say I have this number here 100675
how to turn it into 101000
all the solution I have found on google are solving decimals number.
The bash shell is able to do calculations internally, such as with the following transcript:
pax:~> for x in 100675 100499 100500 100999 101000; do
...:~> ((y = (x + 500) / 1000 * 1000))
...:~> echo " $x becomes $y"
...:~> done
100675 becomes 101000
100499 becomes 100000
100500 becomes 101000
100999 becomes 101000
101000 becomes 101000
This statement, ((y = (x + 500) / 1000 * 1000)), first adds 500 to make the otherwise-truncating integer division by 1,000 into a rounding division, then re-multiplies it by 1,000.
This is a bit of a weird function, but here goes a rough version that might be what you need. At least this could be a starting point.
# in:
# $1 - the number to round
# $2 - the 10 power to round at. Defaults to 3 (i.e. 1000)
# output:
# The rounded number
roundPow()
{
local n="$1"
local pow="${2:-3}"
local div="$((10 ** pow))"
echo "$((((n + div / 2) / div) * div))"
}
This is very rough around the edges, it's not validating parameters, etc, but should give you a baseline.
Hope this helps.
I'm making a query in soql to calculate the mean value of two numeric fields H01 and H02 in a json file, whose values are 6 and 4, respectively. This query gets a single record. The query is like this:
query="SELECT H01,H02, $((H01 + H02))/2 AS AVERAGE WHERE pollutant = 'H6' AND DATA = '2020-05-08T00:00:00.000' AND location = 'London'"
However, when executing this query, the AVERAGE value gives 0, when in fact it is 10.
What am I doing wrong?
You must include the /2 within $(( )) as in:
$(( (H01 + H02) / 2 ))
Proof of Concept
$ H01=6;H02=4; echo $(( (H01 + H02) /2 ))
5
Note - This does not work for floating point
$ H01=5;H02=4; echo $(( (H01 + H02) /2 ))
4
How can I add a percentage to a number in Ruby?
In this example I want to add 20% to 32.92:
irb(main):001:0> 32.92 * (1 + (20 / 100))
=> 32.92
Google answers with the correct answer; 39.50.
Lets say your base_value is: 39.92.
Your markup is 20.
Integer division will lead to the following:
20 / 100
# => 0
So irb is the right direction. This gives better results:
20.to_f / 100
# => 0.2
So the final calculation will look like this:
final_value = (base_value + (markup.to_f / 100) * base_value).round
This gives you the expected value.
As you don’t mind the result to be floored instead of rounded it’s possible to get correct result using integer division:
final_value = base_value + base_value * markup / 100
20 / 100 returns 0, because it's integer division if you pass integers as arguments. Instead, you can pass floats, like this:
32.92 * (1 + (20.0 / 100.0))
or do simply:
32.92 * 1.2
ARITHMETIC EVALUATION section in bash manual lists following operators among others:
id++ id--
variable post-increment and post-decrement
++id --id
variable pre-increment and pre-decrement
As I understand, ++x and --xx increase or decrease the variable before other operations are performed? For example x++:
$ x=5; echo $(( ++x / 2 ))
3
$ x=5; echo $(( x++ / 2 ))
2
$
However, when are x++ and x-- useful? And in general what is the difference between variable post-increment/decrement and pre-increment/decrement in bash?
Quoting from Increment and decrement operators:
In languages that support both versions of the operators, the
pre-increment and pre-decrement operators increment (or decrement) their operand by 1, and the value of the expression is the resulting
incremented (or decremented) value. In contrast, the post-increment
and post-decrement operators increase (or decrease) the value of
their operand by 1, but the value of the expression is the operand's
original value prior to the increment (or decrement) operation.
So, you'll find:
$ x=5; echo $(( x++ / 2 ))
2
$ echo ${x} // The effect of post-increment is visible here
3
Both post-ops and pre-ops change (increase/decrease) value of the variable.
The difference is what they evaluate to: pre-ops evaluate to the value of the variable after the change, and post-ops - to the value before the change.
When the evaluated value isn't used, there is no difference. I.e. these two lines have the same effect:
((x++))
((++x))
Both pre-ops and post-ops are used to remove the need for an explicit assignment. I.e. make code shorter. So, instead of writing this:
x=$((x + 1))
y=$((x * 5))
You can write this:
y=$((++x * 5))
Conversely, instead of this:
y=$((x * 5))
x=$((x + 1))
You can write this:
y=$((x++ * 5))
Most often these operations are used in loop bodies and loop control expressions.
for X in {18..2500} ; is one line of my script, which means to pick number one by one like: 18,19,20,21,22,23....till 2500
However I find I only need even number right now: 18,20,22,24.....2500
Then what should I do by a slight modify of the line?
Thanks
edit:
It's bash...
My script is now changed to:
#!/bin/bash
TASK=1101;
NUM=9;
TEND=1100;
for X in {18..2500};{
if (X % 2 == 0);
do
echo "$X echo \"Wait until $NUM job is done\" $NUM" ;
NUM=$((NUM+2)) ;
X=$((X+1)) ;
TEND=$((TEND+100)) ;
echo "$X -t $TASK-$TEND jobs.sh" ;
TASK=$((TASK+100)) ;}
done
but got errors like:
line 15: syntax error near unexpected token `do'
You can specify the increment:
for X in {18..2500..2}
A sequence expression takes the form {x..y[..incr]}, where x and y are
either integers or single characters, and incr, an optional increment, is
an integer.
Or
for X in `seq 18 2 2500`
This is not C++. This is a bash script.
Your for-loop needs to start with a do:
for X in {18..2500}; do
Your if-statement syntax looks off. It should probably be something like this, note the then:
if [[ $((X % 2)) == 0 ]]; then
if-blocks end with:
fi
And the for-do block ends with:
done
Better still... do away with the if statement and use Bash's for-loop construct to generate only even numbers:
for ((X = 18; X <= 2500; X += 2)); do
echo "$X echo \"Wait until $NUM job is done\" $NUM" ;
# ...
done
Try the modulus operator. In almost all languages, it'll look something like this:
if (x % 2 == 0) // …Do something
That is valid C code, but can easily be applied to other languages.
You can think of the mod operator as a division sign placed in the same location, but rather than returning the results of the division it returns the remainder. Therefore in this code, if the remainder of a divide-by-two is 0, then it divides evenly by two, and so it's even by definition.
If your language has a for(;;) syntax you can
for (X = 18; X <= 2500; X += 2)
There are a couple things you can do:
use the modulus function for your language:
for x in {18..2500} {
if (x mod 2=0) {
do something;}
step through your For loop 2 at a time:
for x in {18..2500} step 2 {
do something;}