-2

I am working in bash script and i am kind to this script. I have a number as follows

1.0 1.1 1.10 1.11 1.12 1.13 1.14 1.15 1.16 1.2 1.3 1.4 1.5 1.6 1.7 1.8 1.9

I am trying to get highest number from the above numbers. When i use the below script i am getting 1.9 instead of 1.16. Could you please help on this. For simple i have take 3 number

        a=1.9
        b=1.16
        max=1.9
        if (( $(echo "$a < $b" | bc -l ) )); then
                 max=$b
        fi

Excepted result : 1.16

Actual result : 1.9

Cyrus
  • 84,225
  • 14
  • 89
  • 153
  • In addition to what Renaud said: Since `bc` sets exit code 1 if the result is not zero, you could get rid of the `if` construct and simplify it to `bc -l <<<"$a>$b" >/dev/null && max=$b` – user1934428 May 25 '23 at 06:32
  • Are these actually version numbers of some kind? – Mark Dickinson May 25 '23 at 07:19
  • Yes these are version number – varun kumar May 25 '23 at 07:22
  • 1
    Then you don't want to interpret them as floats. As you've discovered, that interpretation changes the ordering. – Mark Dickinson May 25 '23 at 07:25
  • 1
    **If** you **need** to somehow cram version numbers into floats, you need to do it Perl style -- `5.008` instead of `5.8`, `5.016` instead of `5.16`. But I would strongly discourage this -- it is more hassle than it's worth. Depending on your context, you might want to look into [`sort`](https://www.man7.org/linux/man-pages/man1/sort.1.html) and it's `-V` option specifically for version numbers. – DevSolar May 25 '23 at 08:28
  • _highest number_..... Hmmm, my school mathematics lectures are already long in the past, but if I remember right, the number 1.9 **is** much larger than 1.16. Why do you expect 1.16 to by larger? – user1934428 May 25 '23 at 14:11
  • They edited the title of the question to mention _version_ numbers instead of the initial _floating point_ numbers. They wanted GNU `sort -V`. – Renaud Pacalet May 25 '23 at 14:13

2 Answers2

2

If what you want is to find the maximum of your list of numbers considered as version numbers you could use GNU sort instead of bc that has no native operator to compare version numbers:

$ list=(1.0 1.1 1.10 1.11 1.12 1.13 1.14 1.15 1.16 1.2 1.3 1.4 1.5 1.6 1.7 1.8 1.9)
$ printf '%s\n' "${list[@]}" | sort -rV | head -1
1.16
  • list=(1.0 ... 1.9) assigns your numbers to bash array list.
  • printf '%s\n' "${list[@]}" prints the list with one number per line.
  • sort -rV sorts the lines in decreasing order of version numbers.
  • head -1 prints only the first line.

To find the minimum use sort -V instead of sort -rV.

Renaud Pacalet
  • 25,260
  • 3
  • 34
  • 51
  • Hi Renaud thanks for the reply. When i use the above code its showing 1.9 as max but actually i need 1.16 as it is highest number – varun kumar May 25 '23 at 07:20
1

In these cases using awk is better.

#!/bin/bash

a=1.9
b=1.16
max=1.9

if awk -v num1="$a" -v num2="$b" 'BEGIN{if (num1>num2) exit 0; exit 1}'; then
  max=$a
else
  max=$b
fi

echo "The highest number is: $max"

This should do the work, maybe you can try it using a for loop instead for larger comparisons.

  • Hi @misenkashari, i used the below one and it was working but when i use the for loop to compare, it was not working. Could you please on this declare -a t=(1.0 1.1 1.10 1.11 1.12 1.13 1.14 1.15 1.16 1.2 1.3 1.4 1.5 1.6 1.7 1.8 1.9) max=$t[0] for l in ${t[@]}; do if awk -v num1="$max" -v num2="$l" 'BEGIN{if (num1>num2) exit 0; exit 1}'; then max=$l fi done – varun kumar May 25 '23 at 07:14
  • yeah i would gladly assist – misenkashari May 25 '23 at 07:16
  • Instead of using the loop in that way by accessing by index i would suggest this: for number in "${t[@]:1}"; do if awk -v num="$number" -v max="$max" 'BEGIN{if (num>max) exit 0; exit 1}'; then max=$number fi done echo "The highest is: $max" – misenkashari May 25 '23 at 07:24
  • Add the proper indentation for more clarity. I have used the :1 for the step and if you read it this way, should be clear enough. – misenkashari May 25 '23 at 07:25
  • i have used this and the output is 1.9 but instead it should be 1.16. – varun kumar May 25 '23 at 08:54
  • look mathematically 1.9 is greater than 1.16. To compare them in the way you want you should use strings instead and sort them by using the sort builtin in bash. Example: t=("1.16" "1.9" "2.5" "0.5" "10.2") sorted_numbers=($(printf "%s\n" "${t[@]}" | sort -g)) echo "${sorted_numbers[@]}". This would sort them as this: 0.5 1.16 1.9 2.5 10.2 – misenkashari May 25 '23 at 09:05
  • if you have floating point variables find a way to stringify them first and then use this approach to have a proper solution in versioning or whatever you are trying to achive. – misenkashari May 25 '23 at 09:08