0

Hi I have to divide two numbers in #!/bin/sh

$x = 5678
$x/1000

but calculations return only integer: 5.

I need 5,678.

I've tried

$x/1000.0 
$x/1000.0 | bc

on first method expect integer

second method: I don't have bc.

Bart
  • 2,151
  • 1
  • 10
  • 26
user22090909
  • 15
  • 1
  • 4
  • What system are you on that does not have `bc` installed by default? – Kusalananda Aug 27 '19 at 09:45
  • 3
    Related/duplicate [How to do integer & float calculations, in bash or other languages/frameworks?](https://unix.stackexchange.com/questions/40786/how-to-do-integer-float-calculations-in-bash-or-other-languages-frameworks) – ilkkachu Aug 27 '19 at 14:01
  • @Kusalananda, some embedded system with e.g. Busybox? It appears to have an implementation of `bc`, since last December (version 1.30.0), but it might not be compiled in, or it might be an older version. – ilkkachu Aug 27 '19 at 14:10

2 Answers2

3

You can use awk:

#! /bin/sh -
x=5678 y=1000
awk -- 'BEGIN{printf "%.3f\n", ARGV[1]/ARGV[2]}' "$x" "$y"

Whether you'll get 5.678 or 5,678 will depend on the locale ($LC_ALL, $LC_NUMERIC, $LANG variables) and the implementation of awk (some of which will use . regardless of the locale).

With the GNU implementation of awk, you need to pass a POSIXLY_CORRECT variable into its environment for it to honour the locale for the decimal radix character.

That also applies to input numbers:

$ LC_ALL=fr_FR.UTF-8 POSIXLY_CORRECT=1 gawk -- 'BEGIN{
   printf "%.3f\n", ARGV[1]/ARGV[2]}' 1,2 10
0,120
$ LC_ALL=fr_FR.UTF-8 POSIXLY_CORRECT=1 gawk -- 'BEGIN{
   printf "%.3f\n", ARGV[1]/ARGV[2]}' 1.2 10
0,100

(in that latter case, the 1.2 was interpreted as 1, because when doing an explicit conversion of string to number (like when using the / arithmetic operator here), awk parses as much of the string as it can as long as it makes a valid number and ignores the rest. That .2 is not understood in that French locale as the decimal radix is , there, not .).

The --, to mark the end of options is needed in the busybox implementation of awk which you seem to be using as it accepts options after non-option arguments, which makes it non-POSIX compliant. Without it, the above wouldn't work if $x or $y were negative number.

Alternatvely, you could again set $POSIXLY_CORRECT, which would force it to parse its options the standard way. Note that in any case, busybox awk always uses . as the decimal radix character regardless of the locale and regardless of $POSIXLY_CORRECT.

Stéphane Chazelas
  • 522,931
  • 91
  • 1,010
  • 1,501
1

you can use the following dc snippet to get the result:

$ dc -e "3k $x 1000/p"
Rakesh Sharma
  • 393
  • 1
  • 3
  • `echo "3k $x 1000/p" | dc` would be more portable. `-e` is not a standard option. Note negative numbers have to be entered as `_12345` instead of `-12345` and the decimal radix is going to be `.` regardless of the locale. – Stéphane Chazelas Aug 27 '19 at 09:09