1

Here is some simple test code.

#!bin/bash cpm=(0 1 0.094) lv=1 attack=5 defense=9 stamina=16 echo $((cpm[lv])) mycpm=$((cpm[lv])) #mycpm=`echo "0.094" | bc -l` cq=`echo "$attack*$defense*1/10*sqrt($stamina)*2^2*$mycpm" | bc -l` echo $cq 

Terminal output:

bash testing.sh 1 72.00000000000000000000 

Okay, great.

Then if I change the third line to lv=2

bash testing.sh testing.sh: line 7: 0.094: syntax error: invalid arithmetic operator (error token is ".094") testing.sh: line 8: 0.094: syntax error: invalid arithmetic operator (error token is ".094") (standard_in) 2: syntax error 

So how am I supposed to use decimals from an array? I cannot find any thing with duckduckgoing. The closest are links to for loop arrays where they figure out how to iterate by +0.1 each step. Otherwise its tutorials that all use integers. I have a preconstructed array and I just need to get values out of it to use in expressions.

Line 10 will work if I actually take out the $mycpm and change that to 0.094. It'll evaluate that just fine. It's just the problem if being able to use an array to have this value.

Is what I want to achieve possible in bash?

2
  • Just try another interpreter language. Commented Feb 3, 2023 at 7:52
  • If there's anything more than the default bash, sure! I did discover zsh in other threads about decimal issues, which was suggested in steeldriver's response, but it does confusing stuff like change the array indeces system. bash is 0-index, zsh is 1-index, from trial and error. But you're right, bash / zsh are probably simply too slow. If 16*16*16*101 = 413696 if my mental math is right evaluations (and preceeding and succeeding variable assignments) take even a minute, let alone 5, I definitely need a faster language. Commented Feb 4, 2023 at 4:47

1 Answer 1

3

The issue here is not the array - it's the fact that bash does not support arithmetic evaluation of non-integers. You'd get the same error with a scalar variable or even a scalar constant:

$ bash -c 'echo $((0.094))' bash: 0.094: syntax error: invalid arithmetic operator (error token is ".094") 

Some other shells, notably zsh, ksh93 and yash do support it, though beware that ksh93 and yash honour the locale's decimal radix character each in they own way and unquoted arithmetic expansion undergo IFS-splitting in both ksh93 and yash (like in bash):

$ zsh -c 'echo $((0.094))' 0.094 
$ LC_ALL=fr_FR.UTF-8 ksh93 -c 'echo "$((0.094))"' ksh93: 0.094: radix point '.' requires LC_NUMERIC=C $ LC_ALL=C ksh93 -c 'echo "$((0.094))"' 0.0939999999999999858 $ LC_ALL=fr_FR.UTF-8 ksh93 -c 'echo "$((0,094))"' 0,0939999999999999858 
$ LC_ALL=fr yash -c 'echo "$((0.094))"' 0.094 $ LC_ALL=fr_FR.UTF-8 yash -c 'echo "$((0.094))"' 0,094 

However there's no need to even try to evaluate the expression in the shell - you can leave that to bc, simply assigning the un-evaluated parameter expansion ${cpm[lv]} to your variable:

#!/bin/bash cpm=(0 1 0.094) lv=2 attack=5 defense=9 stamina=16 echo "${cpm[lv]}" mycpm=${cpm[lv]} #mycpm=$(echo "0.094" | bc -l) cq=$(echo "$attack*$defense*1/10*sqrt($stamina)*2^2*$mycpm" | bc -l) echo "$cq" 

then

$ ./testing.sh 0.094 6.76800000000000000000 

I also replaced the deprecated `backticks` with modern $(command substitution) and added some quotes.

6
  • Oh, I had no idea the curly brackets meant anything. So they will just take the raw value? That sounds like I should use that as standard and more rarely use the parentheses. Are there other use cases for curly brackets, and/or other scenarios where they are better (or parentheses are just wasteful)? I think learning about curly brackets here is the trick, simply because bc couldn't accept the array. Gotta test that code and play some more, thanks! Commented Feb 4, 2023 at 4:53
  • @Tim50001 see the bash manual sections Shell Parameter Expansion versus Arithmetic Expansion Commented Feb 4, 2023 at 13:35
  • This answer doesn't seem to work in my use case. Is there something more I have to do inside a for loop? In isolation, this works in a testing script dedicated to it. But in my actual use case, some of this occurs in a for loop. I assigned the values of attack, defense, stamina outside of the loop. Is that a problem? Otherwise I just keep getting stuff like (standard_in) 1: syntax error (standard_in) 1: syntax error (standard_in) 2: syntax error Commented Feb 4, 2023 at 19:35
  • Despite comments limiting format, this is where I'm at now having done copy and paste from steels' code and it not working. This is still just a snippet, my actual arrays are 1000+ entries long. ``` baseattack=$((att[3])) basedefense=$((def[3])) basestamina=$((hp[3])) for ((lv = 1; lv < 101; lv++)); do mycpm=${cmp[lv]} echo $baseattack #works, my terminal echos the value "198" cq=$(echo "$baseattack*$basedefense*1/10*sqrt($basestamina)*2^2*$mycpm" | bc -l) #yells syntax error: (standard_in) 2: syntax error echo cq=$cq #outputs ct= exit #yeah, there's no value for $ct ``` Commented Feb 4, 2023 at 19:43
  • Nvm, I found the typo. Somewhere I typed cmp instead of cpm. So is there a way to know what these different syntax errors mean? Like "variable not found" or something? Commented Feb 4, 2023 at 19:58

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.