Fonction suivante arrondir l'argument 'x' aux chiffres 'd' :
define r(x, d) {
auto r, s
if(0 > x) {
return -r(-x, d)
}
r = x + 0.5*10^-d
s = scale
scale = d
r = r*10/10
scale = s
return r
}
Votre astuce pour ajouter 0.0005
n'est pas une mauvaise idée. Cependant, cela ne fonctionne pas tout à fait de cette façon. scale
est utilisé en interne lorsque bc
effectue certaines opérations (comme les divisions).
Dans votre cas, il serait préférable d'effectuer d'abord la division, peut-être en utilisant un grand scale
ou le -l
passer à bc
(si votre version le supporte), puis ajoutez 0.0005
puis définissez scale=3
et effectuer une opération impliquant scale
en interne pour que la troncature soit effectuée.
Quelque chose comme :
`a=$sum/$n+0.0005; scale=3; a/1`
Bien sûr, vous voudrez procéder différemment si sum
est positif ou négatif. Heureusement, bc
a des opérateurs conditionnels.
`a=$sum/$n; if(a>0) a+=0.0005 else if (a<0) a-=0.0005; scale=3; a/1`
Vous voudrez ensuite formater cette réponse en utilisant printf
.
Enveloppé dans une fonction round
(où vous pouvez éventuellement sélectionner le nombre de chiffres décimaux):
round() {
# $1 is expression to round (should be a valid bc expression)
# $2 is number of decimal figures (optional). Defaults to three if none given
local df=${2:-3}
printf '%.*f\n' "$df" "$(bc -l <<< "a=$1; if(a>0) a+=5/10^($df+1) else if (a<0) a-=5/10^($df+1); scale=$df; a/1")"
}
Essayez-le :
gniourf$ round "(3+3+4)/3"
3.333
gniourf$ round "(3+3+5)/3"
3.667
gniourf$ round "-(3+3+5)/3"
-3.667
gniourf$ round 0
0.000
gniourf$ round 1/3 10
0.3333333333
gniourf$ round 0.0005
0.001
gniourf$ round 0.00049
0.000
avec le -l
commutateur, scale
est défini sur 20
, ce qui devrait suffire amplement.
Cette solution n'est pas si flexible (elle convertit simplement float en int), mais elle peut gérer les nombres négatifs :
e=$( echo "scale=0; (${e}+0.5)/1" | bc -l )
if [[ "${e}" -lt 0 ]] ; then
e=$(( e - 1 ))
fi