You can use Zsh.
Most shells, including Bash, don't directly support floating-point computations, and as Oli has explained, the typical workaround is to call
bc. However, you have a number of other options.
One of them is to use the Z Shell.
zsh is a Bourne-style shell (same "family" as Bash) that does directly support floating point computations. So if you're willing to make it a Zsh script instead of a Bash script, you can do that by changing the first line of your script from
Once you do that, it will automatically work! In this case, no further modifications to the script are required. (Sometimes, a Bash feature and the corresponding Zsh feature work differently so translating a script from Bash to Zsh requires you to make changes. Though sometimes a Bash script with mistakes in it can actually become correct when treated as a Zsh script, due to different design decisions in Zsh about what expansions should be performed automatically.)
This is the output:
0.5000000000 + 1.5000000000
1.5000000000 + 2.5000000000
2.5000000000 + 3.5000000000
3.5000000000 + 4.5000000000
4.5000000000 + 5.5000000000
5.5000000000 + 6.5000000000
6.5000000000 + 7.5000000000
7.5000000000 + 8.5000000000
8.5000000000 + 9.5000000000
9.5000000000 + 10.5000000000
You'll need Zsh installed for it to run. Zsh does not generally come preinstalled on Ubuntu but it's provided by the
zsh package. If you don't have
zsh then you'll see an error like:
-bash: ./your-script: /bin/zsh: bad interpreter: No such file or directory
zsh package gives you both
/usr/bin/zsh. If you want your script to be portable to other systems that have Zsh but in different places, then you might want to use this hashbang line at the top of your script instead:
If the user can run Zsh by typing
zsh and pressing Enter, then putting that at the top of a script will usually work (and run the same
zsh executable the user would run). That won't work on 100% of systems--technically,
env does not itself have to be provided in
/usr/bin--but in practice it's quite rare for it to fail, provided that
zsh is in the user's
For more information on arithmetic evaluation in Zsh, including floating-point arithmetic, see 11 Arithmetic Evaluation in The Z Shell Manual.
Decreasing Output Precision
A floating-point variable
x in Zsh may show more precision than you want when you expand it like
% echo "$x"
One way to expand it without those extra zeros is to use arithmetic expansion instead:
% echo "$((x))"
You can also use the
printf command to display a value with limited precision:
% printf '%.2f\n' "$x"
That works in other shells, too, even when the shell doesn't support floating-point arithmetic. (Some shells don't have a
printf builtin, but you can still use that command because a standalone-executable version is installed at
printf command won't perform other arithmetic, though, besides rounding.
Even in situations where you don't need numeric formatting,
printf is often a better choice than
echo in shell scripts.
In case you're interested, the Zsh manual (as referenced above) explains how precisely floating point-values are actually stored. (Usually it's IEEE 754 binary64.)
You can use simpler syntax (in Bash, too).
Your script is okay as it is, but you can simplify its syntax for improved readability:
- Your script doesn't need the grouping provided by
; is redundant at the end of a line.
$i can just be written
- You can use
)) rather than
let. Without a leading
$, it evaluates without expanding to the result. Not all shells support this non-expansion form, but Bash and Zsh (and some others) do.
- It's good to quote when you don't want word-splitting to occur even when doing so is optional (as in this case). But you can enclose more than one expansion in the same double-quoted span of text.
Leaving out the bit about
n at the beginning (you may very well need that for your purpose, but I cannot tell what it's for), I suggest:
for ((i = .5; i < 10; i++))
((c = i + 1))
echo "$i + $c"
Or, if you don't want those extra zeros to be printed:
for ((i = .5; i < 10; i++))
echo "$((i)) + $((i + 1))"
0.5 + 1.5
1.5 + 2.5
2.5 + 3.5
3.5 + 4.5
4.5 + 5.5
5.5 + 6.5
6.5 + 7.5
7.5 + 8.5
8.5 + 9.5
9.5 + 10.5
Finally, to address one point of possible confusion:
- It is okay to assign
i = .5 because this was evaluated as an arithmetic expression, due to appearing inside
)), and so spaces around
= were allowed. The spaces are not required and you need not use them, but you may do so. (I have done so.)
- Outside of an arithmetic expression, assigning a shell variable requires there to be no spaces on either side of
=. That is, normally you must write
var = val. Similarly, outside of an arithmetic expression, accessing the value of a shell variable requires