Lets say I have several floating point numbers to print in a Bash script.
But I want the floating points numbers displayed accordingly to the LC_NUMERIC
locale environment variable.
#!/usr/bin/env bash
# For consistent/reproducible error messages in this sample code
LANGUAGE=C
# The speed of light in vacum in m.s
declare -r const_C=299792458
# Declare separately when assigning command output
declare -- const_pi
# π is 4 × arc-tangent of 1, using bc calculator with math library
typeset -r const_pi="$(bc --mathlib <<<'scale=20; 4*a(1)')"
# Do it in US's English
LC_NUMERIC=en_US.utf8
printf 'LC_NUMERIC=%s\n' "${LC_NUMERIC}"
printf 'Speed of light in vacuum is:\nC=%.f m/s\n\nπ=%.10f\n' \
"${const_C}" \
"${const_pi}"
echo $'\n'
# Do it in France's French
# it fails because floating point format
# changes for printf parameters
LC_NUMERIC=fr_FR.utf8
printf 'LC_NUMERIC=%s\n' "${LC_NUMERIC}"
printf 'La vitesse de la lumière dans le vide est :\nC=%.f m/s\n\nπ≈%.10f\n' \
"${const_C}" \
"${const_pi}"
Actual output:
LC_NUMERIC=en_US.utf8
Speed of light in vacuum is:
C=299792458 m/s
π=3.1415926536
LC_NUMERIC=fr_FR.utf8
La vitesse de la lumière dans le vide est :
C=299792458 m/s
a.sh: line 29: printf: 3.14159265358979323844: invalid number
π≈3,0000000000
This is a perfectly expected result because printf
%f
format expects the argument be formatted according to LC_NUMERIC
.
Then how do you display arbitrary floating-point numbers that are stored in POSIX or bc
's format but having display reflect the settings of LC_NUMERIC
?
What if I want the French part of the code, with the following output?
Expected output for French:
La vitesse de la lumière dans le vide est :
C=299792458 m/s
π≈3,1415926536
LC_ALL is an environment variable that overrides all of these. It is typically used in scripts that run particular programs. For example, configure scripts generated by GNU autoconf use LC_ALL to make sure that the configuration tests don't operate in locale dependent ways.
Select Start > All Programs > Accessories > Command Prompt. 2. In the command window that opens, enter echo %VARIABLE%. Replace VARIABLE with the name of the environment variable you set earlier.
Every format specifier begins with the percentage ( %) symbol; a type character follows it. The format specifier for floating-point numbers deals with a number’s fractional and integral parts. We can format the values of double, Double, float, Float, and BigDecimal data types using floating-point number format specifiers.
Not all real numbers can exactly be represented in floating point format. For any numberwhich is not floating point number, there are two options for floating point approximation, say, the closest floating point number less than x as x_ and the closest floating point number greater than x as x+.
To format the float value up to two decimal places, use the % .2f. x = 211911461911461819112146 y = 2**70 z = x / y print ( "%.2f" % z) To format up to three decimal places, use the %.3f. x = 211911461911461819112146 y = 2**70 z = x / y print ( "%.3f" % z)
Accuracy in floating point representation is governed by number of significant bits, whereas range is limited by exponent. Not all real numbers can exactly be represented in floating point format.
This is a problem with Bash's own built in printf command. The standalone printf works OK.
LC_NUMERIC=fr_FR.UTF8 printf 'Bad : %f\n' 3.14
env LC_NUMERIC=fr_FR.UTF8 printf 'Good : %f\n' 3.14
Output
script.sh: line 4: printf: 3.14: invalid number
Bad : 0,000000
Good : 3,140000
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With