Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Use bash to round a decimal part to interger.

30 views
Skip to first unread message

Hongyi Zhao

unread,
May 19, 2015, 8:34:51 AM5/19/15
to
Hi all,

In awk, it has the int() to round a decimal part to interger.

But, how to do it with the pure bash/shell method?

Regards
--
.: Hongyi Zhao [ hongyi.zhao AT gmail.com ] Free as in Freedom :.

Stephane Chazelas

unread,
May 19, 2015, 8:40:09 AM5/19/15
to
2015-05-19 12:34:48 +0000, Hongyi Zhao:
> Hi all,
>
> In awk, it has the int() to round a decimal part to interger.
>
> But, how to do it with the pure bash/shell method?

What kind of number should it handle?

0.92312
1.12e10
-123.2
123E-3

?

Contrary to zsh or ksh93, bash has no support for floating point
arithmetic. So you'll need to call a program that does like awk
or bc. That's what shells are about after all: call commands.

--
Stephane

Janis Papanagnou

unread,
May 19, 2015, 8:44:26 AM5/19/15
to
On 19.05.2015 14:34, Hongyi Zhao wrote:
> Hi all,
>
> In awk, it has the int() to round a decimal part to interger.
>
> But, how to do it with the pure bash/shell method?

You don't have FP support in pure bash (and also not in most shells).

In ksh you can use int() and floating point numbers in arithmetic expressions.

Otherwise it might suffice to use: v=$( printf "%d" 3.14 ) and suppress the
error message.

Janis

>
> Regards
>

Stephane Chazelas

unread,
May 19, 2015, 8:50:09 AM5/19/15
to
2015-05-19 13:38:13 +0100, Stephane Chazelas:
$ X=-123e-1 zsh -c 'zmodload zsh/mathfunc; echo $((int(X)))'
-12
$ X=-123e-1 zsh -c 'zmodload zsh/mathfunc; echo $((floor(X)))'
-13.
$ X=-123e-1 ksh -c 'echo "$((floor(X)))"'
-13
$ X=-123e-1 ksh -c 'echo "$((int(X)))"'
-13
$ X=-123e-1 awk 'BEGIN{print int(ENVIRON["X"])}'
-12

--
Stephane

Kenny McCormack

unread,
May 19, 2015, 8:53:56 AM5/19/15
to
In article <mjfb78$drv$1...@news.m-online.net>,
Um, in bash, I get:

$ printf "The number is: %d\n" 3.14
-bash: printf: 3.14: invalid number
The number is: 0
$

--
Debating creationists on the topic of evolution is rather like trying to
play chess with a pigeon --- it knocks the pieces over, craps on the
board, and flies back to its flock to claim victory.

Stephane Chazelas

unread,
May 19, 2015, 8:55:09 AM5/19/15
to
2015-05-19 14:44:24 +0200, Janis Papanagnou:
(note that bash's printf has a "-v" option to avoid the command
substitution).

$ bash -c "printf '%d\n' 123e-1"
bash: line 0: printf: 123e-1: invalid number
123
$ zsh -c "printf '%d\n' -123e-1"
-12
$ ksh -c "printf '%d\n' -123e-1"
-12
$ dash -c "printf '%d\n' -123e-1"
dash: 1: printf: -123e-1: not completely converted
-123
$ lksh -c "printf '%d\n' -123e-1"
printf: -123e-1: not completely converted
-123
$ /usr/bin/printf '%d\n' -123e-1
/usr/bin/printf: -123e-1: value not completely converted
-123

bash's and other printf implementations other than ksh93 and
zsh's only stop at the first non-digit, so you might as well do
it as:

f=123.123
d=${f%%.*}

--
Stephane

Stephane Chazelas

unread,
May 19, 2015, 9:35:09 AM5/19/15
to
2015-05-19 12:53:53 +0000, Kenny McCormack:
> In article <mjfb78$drv$1...@news.m-online.net>,
> Janis Papanagnou <janis_pa...@hotmail.com> wrote:
[...]
> >Otherwise it might suffice to use: v=$( printf "%d" 3.14 ) and suppress the
> >error message.
>
> Um, in bash, I get:
>
> $ printf "The number is: %d\n" 3.14
> -bash: printf: 3.14: invalid number
> The number is: 0
[...]

It seems you get "0" in bash-4.0 and 3 in 4.1 and above.

--
Stephane

Chris F.A. Johnson

unread,
May 21, 2015, 2:08:07 AM5/21/15
to
On 2015-05-19, Hongyi Zhao wrote:
> Hi all,
>
> In awk, it has the int() to round a decimal part to interger.
>
> But, how to do it with the pure bash/shell method?

Assuming that the number is in the decimal form, N.N:

var=12.34
int=${var%.*}


--
Chris F.A. Johnson

Hongyi Zhao

unread,
May 21, 2015, 2:37:58 AM5/21/15
to
On Thu, 21 May 2015 01:44:21 -0400, Chris F.A. Johnson wrote:

> Assuming that the number is in the decimal form, N.N:
>
> var=12.34 int=${var%.*}

Thanks.

Wayne

unread,
May 21, 2015, 11:56:35 PM5/21/15
to
On 5/21/2015 2:37 AM, Hongyi Zhao wrote:
> On Thu, 21 May 2015 01:44:21 -0400, Chris F.A. Johnson wrote:
>
>> Assuming that the number is in the decimal form, N.N:
>>
>> var=12.34 int=${var%.*}
>
> Thanks.
>
> Regards
>

To round a number in Bash:

printf '%.0f\n' 3.6 # prints "4"

The "${var%.*}" expansion truncates, but
does not round.

printf should work for Bash, ksh, zsh, and even
dash. (POSIX does not require printf to support
the "%f" conversion, but most shells seem to,
and /usr/bin/printf on my Gnu Linux system does
as well.)

If you want a portable solution, and don't mind
a non-Bash answer:
$ NUM=3.6
$ awk 'BEGIN { printf "%.0f\n", '"$NUM"' }'
4


--
Wayne

Hongyi Zhao

unread,
May 22, 2015, 12:21:32 AM5/22/15
to
On Thu, 21 May 2015 23:56:28 -0400, Wayne wrote:

> To round a number in Bash:
>
> printf '%.0f\n' 3.6 # prints "4"
>
> The "${var%.*}" expansion truncates, but does not round.
>
> printf should work for Bash, ksh, zsh, and even dash. (POSIX does not
> require printf to support the "%f" conversion, but most shells seem to,
> and /usr/bin/printf on my Gnu Linux system does as well.)
>
> If you want a portable solution, and don't mind a non-Bash answer:
> $ NUM=3.6 $ awk 'BEGIN { printf "%.0f\n", '"$NUM"' }'
> 4

Thanks a lot.

Chris F.A. Johnson

unread,
May 22, 2015, 1:08:06 AM5/22/15
to
On 2015-05-22, Wayne wrote:
> On 5/21/2015 2:37 AM, Hongyi Zhao wrote:
>> On Thu, 21 May 2015 01:44:21 -0400, Chris F.A. Johnson wrote:
>>
>>> Assuming that the number is in the decimal form, N.N:
>>>
>>> var=12.34 int=${var%.*}
>
> To round a number in Bash:
>
> printf '%.0f\n' 3.6 # prints "4"

Or, to store the result in a variable:

printf -v varname '%.0f\n' 3.6

> The "${var%.*}" expansion truncates, but
> does not round.

I should have noticed that the OP asked for it to be rounded not
truncated.

--
Chris F.A. Johnson

Hongyi Zhao

unread,
May 22, 2015, 2:09:24 AM5/22/15
to
On Fri, 22 May 2015 01:03:57 -0400, Chris F.A. Johnson wrote:

> printf -v varname '%.0f\n' 3.6

Graceful solution. Thanks a lot.

>
>> The "${var%.*}" expansion truncates, but does not round.
>
> I should have noticed that the OP asked for it to be rounded not
> truncated.

Yes, thanks.

Stephane Chazelas

unread,
May 22, 2015, 6:35:10 AM5/22/15
to
2015-05-22 01:03:57 -0400, Chris F.A. Johnson:
> On 2015-05-22, Wayne wrote:
> > On 5/21/2015 2:37 AM, Hongyi Zhao wrote:
> >> On Thu, 21 May 2015 01:44:21 -0400, Chris F.A. Johnson wrote:
> >>
> >>> Assuming that the number is in the decimal form, N.N:
> >>>
> >>> var=12.34 int=${var%.*}
> >
> > To round a number in Bash:
> >
> > printf '%.0f\n' 3.6 # prints "4"
>
> Or, to store the result in a variable:
>
> printf -v varname '%.0f\n' 3.6

Note that in that case you can drop the \n:

printf -v varname %.0f 3.5

> > The "${var%.*}" expansion truncates, but
> > does not round.
>
> I should have noticed that the OP asked for it to be rounded not
> truncated.
[...]

Note that the number if first converted to the internal floating
point format and then subject to the rounding operator, which
can give some simingly inconsistent results:

$ printf '%.0f\n' 15e-1 25e-1 3.5 4.5
2
2
4
4

The rint() of ksh93 or zsh have a similar limitation, but not
the round() of ksh93 it would seem.

--
Stephane

Geoff Clare

unread,
May 22, 2015, 10:11:07 AM5/22/15
to
Stephane Chazelas wrote:

> Note that the number if first converted to the internal floating
> point format and then subject to the rounding operator, which
> can give some simingly inconsistent results:
>
> $ printf '%.0f\n' 15e-1 25e-1 3.5 4.5
> 2
> 2
> 4
> 4

These results are exactly what you should expect if you know that the
default rounding mode for IEEE floating point is "Round to nearest,
ties to even".

> The rint() of ksh93 or zsh have a similar limitation, but not
> the round() of ksh93 it would seem.

This is how the underlying C library functions are required to work.
Quoting SUSv4:

round():
"... to the nearest integer value in floating-point format, rounding
halfway cases away from zero, regardless of the current rounding
direction."

rint():
"If the current rounding mode rounds towards nearest, then rint()
differs from round in that halfway cases are rounded to even rather
than away from zero."

--
Geoff Clare <net...@gclare.org.uk>

Stephane Chazelas

unread,
May 22, 2015, 11:00:09 AM5/22/15
to
2015-05-22 14:44:39 +0100, Geoff Clare:
> Stephane Chazelas wrote:
>
> > Note that the number if first converted to the internal floating
> > point format and then subject to the rounding operator, which
> > can give some simingly inconsistent results:
> >
> > $ printf '%.0f\n' 15e-1 25e-1 3.5 4.5
> > 2
> > 2
> > 4
> > 4
>
> These results are exactly what you should expect if you know that the
> default rounding mode for IEEE floating point is "Round to nearest,
> ties to even".
[...]

Thanks. I stand corrected. My statement about internal floating
point formats is probably also not relevant since a xxxxxx.5
float is encoded without loss as a float/double.

--
Stephane
0 new messages