Arithmetic on a Float in bash

I am using bash
I have a script that takes a number, i.e. 85.152, which is always a non integer and essentially tries to get that number to be a multiple of 10. My code is as follows:

number=85.152
A=${number%.*} #Converts float to integer
typeset -i B=$(((A-20)/10)) #subtracting 20 is desired, dividing by 10 is done to get the value less than 10 (only works for numbers less than 100)
typeset -i C=${B%.*} #converts float to integer (redundant I know, but necessary)
typeset -i answer=$((C * 10)) #Gives me a multiple of 10

Explanation:

  1. I convert from a float to integer first because I cannot simply divide 85.152 by 10 using bash. It does not like dividing floats.
  2. I subtract 20 because this is desired by design (it can be ignored). The division by 10 gets me to a number below 10 which is just a trick because any integer less than 10 which is multiplied by 10 will simply be a multiple of 10.
  3. I convert from float to integer again just in case the number I divided, (to get less than 10), ends up dividing out to be another float (i.e. 85/10=8.5, then truncate to 8).
  4. Finally I multiply by 10, 8*10=80 which is a multiple of 10.

I did what I could as a newbie to make it work but now I would like to simplify this process. I simply want to take 85.152 and make it a multiple of 10 that is 20 less than 85.152. So answer = (85.125-20) truncated to a multiple of 10. Should be 60. Any suggestions?

Not sure what you mean. Something like this maybe?

answer=$(((${number%.*}-20)/10*10))

or

answer=$(((${number%.*}/10-2)*10))
$ V=85.5
$ echo $(( ${V%.*}-(${V%.*}%10)-20 ))

60

$

OSX 10.7.5, default bash terminal...
How about:-

Last login: Sat Oct 24 08:38:01 on ttys000
AMIGA:barrywalker~> x=87.1173
AMIGA:barrywalker~> y=20
AMIGA:barrywalker~> echo $[${x%.*}-${x%.*}%10-$y]
60
AMIGA:barrywalker~> _
x=85.152
y=20
$ echo "(($x-$y)/10)*10"|bc 
60

How about

number=85.152
echo $((${number%?.*}0 - 20 ))
60
number=895.152
echo $((${number%?.*}0 - 20 ))
870
1 Like

Hi RudiC...
Neat!
Contracting on your method, OSX 10.7.5, default bash terminal:-

Last login: Sat Oct 24 17:08:09 on ttys000
AMIGA:barrywalker~> number=87.11234
AMIGA:barrywalker~> echo $[${number%?.*}0-20]
60
AMIGA:barrywalker~> number=897.1357
AMIGA:barrywalker~> echo $[${number%?.*}0-20]
870
AMIGA:barrywalker~> _

EDIT:-
Important note both methods do not work with the number 80 but do if converted to 80.0 float equivalent.

Note: the $[ ... ] is a non-standard, bash-specific legacy construct that has been deprecated since bash 2.0 and is now no longer in the man pages, so it should be regarded as an undocumented feature, which could be removed from future versions..

Instead, $(( .. )) should be used, which is also used in any other POSIX compliant shell.

As this little trick doesn't really do arithmetics, it needs the dot to lock in on.

Thanks...

I was/am aware, but the OP is using bash.
Sadly, I use(d) this method in AudioScope.sh from day one so that code is lumbered with this legacy.
However apart from my important note I did like RudiC's approach so I decided to reduce the number of characters, (ignoring spaces).
I will refrain from using this method again but will have to continue using it in the above project to keep the coding style the same...

Once again thanks and I will use the parentheses method in any future help...

Save another char? echo $((${number%?.*}-2))0

1 Like

Terrific stuff, that is cool...

I just love your lateral thinking head...

Dare I use square brackets and reduce it by another two characters?
Only joking... ;oD

Nice, a tiny nitpick would be that number=28.152 results in 00 ...

1 Like