Rounding up float point numbers bash
In case input
contains a number, there is no need for an external command like bc
. You can just use printf
:
printf "%.3f\n" "$input"
Edit: In case the input is a formula, you should however use bc
as in one of the following commands:
printf "%.3f\n" $(bc -l <<< "$input")
printf "%.3f\n" $(echo "$input" | bc -l)
Floating point rounding in shell
It has to do with floating-point, but not with double-precision.
When you write
printf "%0.2f\n" 41.495
on your system, printf
first rounds 41.495
to the closest x87 80-bit floating-point number[1]. How does that work? First write 41.495 in binary:
b101001.0111 11101011100001010001 11101011100001010001 11101011100001010001 ...
(the separated groups repeat ad infinitum). Now we round this number to have 64 binary digits:
b101001.0111111010111000010100011110101110000101000111101011100001
This is the number that is actually formatted by printf. Written in decimal, it is exactly:
41.4949999999999999990285548534529880271293222904205322265625
as you can see, it is just a little bit less than 41.495, so when printf rounds it to two fractional digits, it rounds down, and 41.49
is printed.
Now look at 41.485; after rounding to 64 binary digits, we get the value:
41.48500000000000000055511151231257827021181583404541015625
which is just a little bit bigger than 41.485, so printf rounds it up.
On my system, there is a warning about this in the printf manage:
Since the floating point numbers are translated from ASCII to floating-point and then back again, floating-point precision may be lost.
- bash doesn't use the x87 format on all operating systems (indeed, it isn't even available on all architectures); on some other systems these values will be interpreted as doubles (and therefore rounded to 53 bits instead of 64), and the results will differ.
How to round a floating point number upto 3 digits after decimal point in bash
What about
a=`echo "5+50*3/20 + (19*2)/7" | bc -l`
a_rounded=`printf "%.3f" $a`
echo "a = $a"
echo "a_rounded = $a_rounded"
which outputs
a = 17.92857142857142857142
a_rounded = 17.929
?
How do I use floating-point arithmetic in bash?
You can't. bash only does integers; you must delegate to a tool such as bc
.
how to round the output in shell?
awk
to the rescue!
awk 'BEGIN {FS=OFS="|"}
$NF==$NF+0 {a=$NF*1.21;
r=a-int(a);
if (r<0.225) a=a-r-0.05;
else if (r<0.725) a=a-r+0.50;
else a=a-r+0.95;
$(NF+1)=a} 1'
note that in your example the nearest number for 30.2379
will be 30.50
Perhaps you want to round down?
To round down instead of the nearest, and with a variable price column. The new computed value will be appended to the end of the row.
awk 'BEGIN {FS=OFS="|"; k=5}
$k==$k+0 {a=$k*1.21;
r=a-int(a);
if (r<0.50) a=a-r-0.05;
else if (r<0.95) a=a-r+0.50;
else a=a-r+0.95;
$(NF+1)=a} 1'
Convert floating point numbers to integer without rounding in bash
You could use awk,
$ echo '2.45, 3.56, 54,64' | awk -v FS=" *, *" '{for(i=1;i<=NF;i++){count = count+$i}}END{print count}'
124.01
bash calculation using bc, and round up floating point
As far as I know only division is using the information given by scale
.
echo "scale=0; (9 * 150 + 8.092 * 560 + 3.181)/1" | bc
will echo 5884 since the integer part (quotient!) was taken only. To get your desired result (round) you might use:
echo "scale=0; ((9 * 150 + 8.092 * 560 + 3.181)+0.5)/1" | bc
note that this approach will not work for negative numbers! See this post: https://unix.stackexchange.com/a/89843
Bash round whole numbers up, down or to nearest hundreds
It's not entirely clear what is meant by "in Bash", but perhaps one of :
$ cat input
827818
6574762
685038
55326902
$ awk '{printf "%d00\n", $0 / 100}' input
827800
6574700
685000
55326900
or (if all the values are greater than 100!):
while read x; do echo "${x%[0-9][0-9]}00"; done < input
If you want to handle the case where values are less than 100 and deal with negative values, you could do:
while read x; do if test "${x#-}" -gt 100; then echo "${x%[0-9][0-9]}00"; else echo 0; fi; done < input
but it's almost certainly better to stick with awk
.
Related Topics
Splitting a Large Directory into Smaller Ones in Linux
How to Programmatically Know If I Am in a Vm
How Is The Linux Calculating Memfree
Linux Compile for Enable Uart2
Linking with 32Bit Libraries Under Linux 64Bit
Ssh - Help Understanding Proxy Command
Setting an Acpi Field in Linux
Bash Linux - Massive Folder Rename
Cannot Kill Redis-Server on Linux
Vue Npm Run Serve Failed to Load Resource: Net::Err_Content_Length_Mismatch
Sublime Text 2 Build (Ctrl +B) Intel Fortran Compiler
Reading Microphone Data by Polling Using Alsa [Or V4L2]
Git Says Everything Up-To-Date
Influxdb Not Asking for Authentication