If I run ./random.sh 10 45, it would only return random numbers between 10 and 45.
I am able to produce the random number using
randomNumber=$((1 + RANDOM % 100))
but now how can I allow user to specify upper and lower limit of random number?
You can use shuf
#!/bin/bash
# $1: Lower limit
# $2: Upper limit
# Todo Check arguments
shuf -i $1-$2 -n 1
./random.sh 45 50
Try the following (pure BASH):
low=10
hgh=45
rand=$((low + RANDOM%(1+hgh-low)))
The idea is to set your range at a default lower bound, say 10, with a higher bound, say 45. So you adjust the lower bound like this : $RANDOM % 45 + 10, don't you?
But there is a problem with this solution, it assumes that you'll always be between 0 + 10 and 45 so in fact it works until you reach 35 (35 + 10 = 45 your higher bound), anymore than 35 will be out of your bounds.
The solution in order to stay in the range is to do $RANDOM % (higher_b - lower_b) which will allow you to stay in higher bound then to add lower bound which gives you :
$RANDOM % (45 -10) + 10
example wrong output:
for i in {0..10};do printf $[RANDOM % 45 + 10]" ";done
47 31 53 23 36 10 22 36 11 25 54
example right output:
for i in {0..10};do printf $[RANDOM % 35 +10]" ";done
39 44 14 12 38 31 25 13 42 33 16
You can also write RANDOM % (higher - lower +1) if you want your index to include higher bound.
The trouble with modulo is that $RANDOM % N, unless N is a power of 2, does not have an equal probability distribution for all results: How to generate random number in Bash?. Per man bash, $RANDOM produces a number between 0 and 32,767 (2**15-1). This may not matter much in some situations, but by rewriting the expression slightly we do get an equal distribution.
for i in {0..10}; do echo -n "$((RANDOM*36/32768 + 10)) "; done; echo
A bash script with a user-selectable range:
#!/bin/bash
LOW=$1
HIGH=$2
echo $((RANDOM * ($HIGH-$LOW+1) / 32768 + LOW))
You will want to do some parameter checking also.
Related
I have a question which I think is fairly simply but I am new to Bash and can't find much info on this.
5 references 3
10 references 4
20 references 10
30 references 20
inputBeforeLookup = 5 #this the number which needs to look up 3 above^^^^
# 10 would lookup and return 4
#20 returns 10
start = 1
end = $start + $lookupNumberfromFile # 3 in this case, since input was 5
seq $start $end
1
2
3
4
I guess my question here is what is the proper way to create like a configuration file which references numbers to other numbers?
If there is a better way than the snippet of code I posted I am always open to suggestions, like i said I am learning.
I am new to this so I am not sure if the syntax is 100% correct. I am more so looking for a solution on the best way to solve the problem.
Hope this sample helps you regarding variable expansion in bash:
Notice that: the \ prevents the expansion of $$ (current process id). For triple substitution you need double eval and so on....
#!/bin/bash
one=1
two=one
three=two
four=three
five=four
echo $one
eval echo \$$two
eval eval echo \\$\$$three
eval eval eval echo \\\\$\\$\$$four
eval eval eval eval echo \\\\\\\\$\\\\$\\$\$$five
Output:
1
1
1
1
1
Bonus:
In zsh you can use nested substitution much more easily:
#!/bin/zsh
one=1
two=one
three=two
four=three
five=four
echo $one
echo ${(P)two}
echo ${(P)${(P)three}}
...
http://zsh.sourceforge.net/Doc/Release/Expansion.html
Set up an associative array, then test it with numbers 1 to 30. Those numbers that don't reference other numbers are printed as is:
MYMAP=( [5]=3 [10]=4 [20]=10 [30]=20 )
seq 30 | while read x ; do echo ${MYMAP[$x]:-$x} ; done | paste - - - - -
That last | paste - - - - - isn't necessary, but 5 column output is easier to follow given that the input has several multiples of 5. Output:
1 2 3 4 3
6 7 8 9 4
11 12 13 14 15
16 17 18 19 10
21 22 23 24 25
26 27 28 29 20
Is there a way to find a value's 2 exponential form in bash.
For example if I input 512 it should result output as 9 meaning 2 ^ 9 is 512.
Any help here is immensely appreciated - Thanks
When I read the question, 512 is the input, and 9 is the output. Is is possible what is being asked here is the answer to "log_base_2(512)" which has an answer of "9". If so, then maybe this would help.
$ echo "l(512) / l(2)" | bc -l
9.00000000000000000008
The explanation of the math can be found here:
How do I calculate the log of a number using bc?
Using awk.
$ echo 512 | awk '{print log($1)/log(2)}'
9
Put that into a script (expo.sh):
#!/bin/bash
_num="$1"
expon=$(awk -v a="$_num" 'BEGIN{print log(a)/log(2)}')
if [[ $expon =~ ^[0-9]+\.[0-9]*$ ]]; then # Match floating points
echo "$_num is not an exponent of 2"; # Not exponent if floating point
else
echo "$_num = 2^${expon}"; # print number
fi
Run:
$ ./expo.sh 512
512 = 2^9
$ ./expo.sh 21
21 is not an exponent of 2
A fast way to check a number x is an 2 exponent is to check bitwise and x and x-1 and to exclude 0, x>0
((x>0 && ( x & x-1 ) == 0 )) && echo $x is a 2-exponent
using this algorithm: fast-computing-of-log2-for-64-bit-integers to compute log2
tab32=( 0 9 1 10 13 21 2 29
11 14 16 18 22 25 3 30
8 12 20 28 15 17 24 7
19 27 23 6 26 5 4 31 )
log2_32() {
local value=$1
(( value |= value >> 1 ))
(( value |= value >> 2 ))
(( value |= value >> 4 ))
(( value |= value >> 8 ))
(( value |= value >> 16 ))
log2_32=${tab32[(value * 16#7C4ACDD & 16#ffffffff)>>27]}
}
log2_32 262144
echo "$log2_32"
This script should give values to the program through the command line and store the output of the terminal in their corresponding files. Since I cannot put a decimal-point number as part of the label of the file, I intent to multiply each kappa by 10000 to turn them into integers and use them as labels, but I did it wrong in the code and I don't know how to it properly. How does it work? Thank you!
#!/bin/bash
for kappa in $(seq 0.0001 0.000495 0.01);
do
kappa_10000 = $kappa * 10000;
for seed in {1..50};
do
./two_defects $seed $kappa > "equilibration_step_seed${seed}_kappa${kappa_10000}.txt";
done
done
Bash does not do floating-number calculation as pointed out by #Inian. A program like bc must be called and its output can be directly stored in a variable as follows:
for kappa in $(seq 0.0001 0.000495 0.01)
do
kappa_10000=$(echo "$kappa*10000/1" | bc)
echo kappa_10000
done
The output in the terminal would be
1
5
10
15
20
25
30
35
40
45
50
55
60
65
70
75
80
85
90
95
100
The /1 operation must be added to make the output an integer.
I have been googling and trying different methods but nothing seems to work.
I have the following code
string=0 4 5 27 8 7 0 6
total=0
for n in "$string"; do
total=$(($total + $n))
done
This way I want to count the total sum of all the numbers within that string.
I have also tried expr "$total" + "$n" but that gives me an error saying the operand is not an integer.
Any suggestion how I might make this work?
Don't quote the string in the in clause, quoted string is not split into words:
#! /bin/bash
total=0
string='0 4 5 27 8 7 0 6'
for n in $string ; do
(( total += n ))
done
echo $total
string=0 4 5 27 8 7 0 6
This attempts to set the variable string to 0, then invoke the command 4 with arguments 5 27 8 7 0 6.
You need to quote the value:
string="0 4 5 27 8 7 0 6"
And you need to remove the quotes when you refer to it; change
for n in "$string"; do
to
for n in $string; do
You should use :
total=$(( total + n ))
no need for the $ before variables inside a $(( )) statement
I am adding a series of 8196 64-bit unsigned integers, and I need the running-total to "roll-over" back to zero and continue counting from there... just as a "normal" programing language would do at the relevent INT_MAX ceiling.
As the test script shows, adding 1 to an boundary value (FF, FFFF, etc) just keeps on increasing the total. A feature, no doubt, but I'd like to limit it to 64-bits for this particular instance..
Is there some way to limit bc in this?
unset f
for ((i=0; i<8; i++)); do
f=${f}FF; echo -ne "$((${#f}/2)) bytes + 1 "
echo 'ibase=16; obase=10; ('$f'+1)' |bc
done
echo "I want 8th+1 to = 0000000000000000"
# output
#
# 1 bytes + 1 100
# 2 bytes + 1 10000
# 3 bytes + 1 1000000
# 4 bytes + 1 100000000
# 5 bytes + 1 10000000000
# 6 bytes + 1 1000000000000
# 7 bytes + 1 100000000000000
# 8 bytes + 1 10000000000000000
# I want 8th+1 to = 0000000000000000
This is called a modulo and you can read https://superuser.com/questions/31445/gnu-bc-modulo-with-scale-other-than-0 here about modulo and bc.