I need some help with a bash mathematical expression script. I need the expression below to be a negative 2 to the power of 63 but I have tried all sorts of combinations from "", '', (()) and even keeping the positive value but multiplying it by -1 but I can't seem to get the syntax right.
Original expression:
kw=`expr 2^63 | bc`
gives me 9223372036854775808 (which is correct) but I need to get a -9223372036854775808.
I want to be able to do a kw=expr -2^63 | bc to get a negative results but it's not as straight-forward as I'd hoped. Hence my numerous attempts of different permutations to the expression.
Any help will be very appreciated.
Here you go:
$ kw=$(echo -2^63 | bc)
$ echo $kw
-9223372036854775808
UPDATE
#DigitalTrauma is right, if you're in bash, then using a bash here string is better (one less process, more efficient):
kw=$(bc <<< -2^63)
Since this is bash, you don't even need the echo; you can use a bash here string instead:
$ kw=$(bc <<< -2^63)
$ echo $kw
-9223372036854775808
Related
Here is my script:
d1=0.003
d2=0.0008
d1d2=$((d1 + d2))
mean1=7
mean2=5
meandiff=$((mean1 - mean2))
echo $meandiff
echo $d1d2
But instead of getting my intended output of:
0.0038
2
I am getting the error Invalid Arithmetic Operator, (error token is ".003")?
bash does not support floating-point arithmetic. You need to use an external utility like bc.
# Like everything else in shell, these are strings, not
# floating-point values
d1=0.003
d2=0.0008
# bc parses its input to perform math
d1d2=$(echo "$d1 + $d2" | bc)
# These, too, are strings (not integers)
mean1=7
mean2=5
# $((...)) is a built-in construct that can parse
# its contents as integers; valid identifiers
# are recursively resolved as variables.
meandiff=$((mean1 - mean2))
Another way to calculate floating numbers, is by using AWK rounding capability, for example:
a=502.709672592
b=501.627497268
echo "$a $b" | awk '{print $1 - $2}'
1.08218
In case you do not need floating point precision, you may simply strip off the decimal part.
echo $var | cut -d "." -f 1 | cut -d "," -f 1
cuts the integer part of the value. The reason to use cut twice is to parse integer part in case a regional setting may use dots to separate decimals and some others may use commas.
Edit:
Or, to automate the regional settings one may use locale.
echo $var | cut -d $(locale decimal_point) -f 1
You can change the shell which you are using. If you are executing your script with bash shell bash scriptname.sh try using ksh for your script execution. Bash doesn't support arithmetic operations that involve floating point numbers.
Big shout-out to the bc command - it totally saved my day! It's a simple answer, but it worked like a charm.
a=1.1
b=1.1
echo $a + $b | bc -l
# Output:
2.2
#SUM
sum=$(echo $a + $b | bc -l)
echo $sum
# Output
2.2
bc is a command-line calculator, which allows users to perform mathematical calculations on the terminal.
I am trying to add two 32 bit binary numbers. One of them is a constant (address_range_in_binary) , and another one is an element of an array (IPinEachSubnet[$val])
I am trying to follow the instructions here, but I could not figure out how to get it done using variables. I have been trying to use different combinations of the below, but none of them seems to work. It is probably a simple syntax issue. Any help would be appreciated. The following is printing some negative random values.
For example, if the values are as following:
$address_range_in_binary=00001010001101110000101001000000
$IPinEachSubnet[$val]=00000000000000000000000000010000
echo "ibase=2;obase=2;$((address_range_in_binary+IPinEachSubnet[$val]))" | bc -l
The output of this is -1011101110111111110
bash only solution
y=2#00001010001101110000101001000000
t=2#00000000000000000000000000010000
oct=$(printf '%o' $(( y + t ))) # no bin format in printf
o2b=({0..1}{0..1}{0..1})
r=''
for (( i=0; i<${#oct}; i++ ))
do
r+=${o2b[${oct:$i:1}]}
done
echo $r
the conversion from oct to bin is inspired in Bash shell Decimal to Binary conversion
Let's define your variables (I will use shorter names):
$ y=00001010001101110000101001000000
$ t=00000000000000000000000000010000
Now, let's run the command in question:
$ echo "ibase=2;obase=2;$((y+t))" | bc -l
-1011101110111111111
The above produces that incorrect result that you observed.
To get the correct result:
$ echo "ibase=2;obase=2; $y+$t" | bc -l
1010001101110000101001010000
Discussion
The command $((y+t)) tells bash to do the addition assuming that the numbers are base-10. The result of bash's addition is passed to bc. This is not what you want: You want bc to do the addition.
Using an array
$ y=00001010001101110000101001000000
$ arr=(00000000000000000000000000010000)
$ echo "ibase=2;obase=2; $y+${arr[0]}" | bc -l
1010001101110000101001010000
I'm trying to figure out a way to take the result of a basic equation and divide by another integer. So in in simple form it looks like;
A-B = C and then divide C by D
I understand the first part of the equation is echo $((A-B)) but how do I get that result divided by D?
Any feedback would be greatly appreciated!
Using shell
This (taken from the comments) fails because the parentheses are unbalanced:
$ echo $((2147483633-807279114))/5184000))
Try instead:
$ echo $(( (2147483633-807279114)/5184000 ))
258
The above returns an integer because the shell only does integer arithmetic.
Using bc
If you want accurate floating-point numbers, the standard tool to use is bc:
$ echo '(2147483633-807279114)/5184000' | bc -l
258.52710628858024691358
Using python
Python supports both integer and floating point arithmetic:
$ python -c 'print (2147483633-807279114)//5184000'
258
$ python -c 'print (2147483633-807279114)/5184000.0'
258.527106289
Python, with its numpy extension, is an excellent tool even if your needs extend to complex scientific calculations.
Using awk
awk, a standard unix tool, supports floating-point math:
$ awk 'BEGIN{print (2147483633-807279114)/5184000;quit}'
258.527
You can do calculations inside $(( ))
If you want to calculate (A-B)/C, you can put that inside $(( )):
echo $(( (A-B)/C ))
Note that the result will be truncated towards zero, because bash does not support decimals.
Remember to make sure that you have $(( before the expression and )) after, and that all the parentheses inside match up.
dc <<< "$A $B - $D / p"
Note 1: p prints the final result
Note 2: With dc you need to first enter the numbers and then operation
I'm trying to run a bash script that includes a nested for loop within which a variable should cycle through negative exponents, viz:
for ABPOW in {-11..-9}
do
ABC = $((10**$ABPOW))
for ABCOEFF in {1..9}
do
sed -e 's/ACOEFF/'$ABC'/'\
This is only the inner two for loops of the code. When the values in the first bracket (for ABPOW) are positive, the code runs fine. However, when I have them as i do above, which is what I need, the error communicated to screen is:
./scripting_test2.bash: line 30: 10**-11: exponent less than 0 (error token is "1")
How do I make this run? Thanks in advance.
PS: I tried putting a negative sign in front of $ABPOW but the exponents are still recorded as positive.
Bash does not support floating point arithmetic (which is necessary for raising something into a negative power). Instead, you should use the bc utility.
ABC=$(bc -l <<< "10 ^($ABPOW)")
Also, there should be no spaces before and after the = in variable assignments
Here's another way:
perl -e 'for $abpow (-11..-9) { $abc=10**$abpow; for (1..9) { system("echo $abc"); } }'
Bash doesn't support floating point data types.
$ man bash|grep -c -i float
0
Do you have python installed?
ABC=$( python -c "print 10**$ABPOW" )
One alternative is to use awk for your complete script that has full support for floating point arithmetic:
awk 'BEGIN{for(i=-11; i<=-9; i++) {ABC=10^i; print ABC}}'
1e-11
1e-10
1e-09
how to remove decimal place in shell script.i am multiplying MB with bytes to get value in bytes .I need to remove decimal place.
ex:-
196.3*1024*1024
205835468.8
expected output
205835468
(You did not mention what shell you're using; this answer assumes Bash).
You can remove the decimal values using ${VAR%.*}. For example:
[me#home]$ X=$(echo "196.3 * 1024 * 1024" | bc)
[me#home]$ echo $X
205835468.8
[me#home]$ echo ${X%.*}
205835468
Note that this truncates the value rather than rounds it. If you wish to round it, use printf as shown in Roman's answer.
The ${variable%pattern} syntax deletes the shortest match of pattern starting from tbe back of variable. For more information, read http://tldp.org/LDP/abs/html/string-manipulation.html
Use printf:
printf %.0f $float
This will perform rounding. So if float is 1.8, it'll give you 2.