Convert floating point numbers to integer without rounding in bash - bash

I have a input file with set of float numbers like 2.45, 3.56, 54,64and so on. I need to sum them.
After reading the this article I understand that there is no straight way to do that. I can't round any numbers.
I remember that there are a way to convert in to int without rounding. Like 2.54 * 100 = 254. After that I can do all math and return it to float view using AWK.
I was trying to use bc tool, but it wont work this way.
Like, (wrong code)
a=2.54
c=$((a * 100)) | bc -l
Please, suggest
Not duplicate, because:
I'm asking and looking to convert floating point numbers to integers, not to compare 2 floating numbers. I need to SUM it, and it is different from comparison. Besides, that question doesn't answer on my question.
Point of asking here is to get closest possible answer for particular question.

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

Related

How to round to 1 decimal in bash?

I am trying my first script on bash and I am not able to round (not truncate).
So, I am getting 55.08 and I would like to convert it to 55.1
promedio=$(echo "scale=2; $lineas/($dias*24)" | bc)
Note that I am currently using scale=2 because scale=1 produces 55.0.
Thank you all :)
This is not so much a bash question as a bc one, but bc doesn’t round. The easiest approach is probably just to add .05 after the division, then set scale to 1 and divide by 1 to force truncation.
You can do that by using a variable inside bc to hold the unrounded result:
promedio=$(bc <<<"scale=2; p=$lineas/($dias*24); scale=1; (p+0.05)/1")
Or you could do it all in one go by throwing in an extra multiplication by 10, rounding at that magnitude, and then dividing back down:
promedio=$(bc <<<"scale=1; (10*$lineas/($dias*24)+0.5)/10")

How to count 100=(100/24)*24 in bash?

I try to perform this simple calculation, but the programm always gives me incorrect results. If I use only integers, then I get 96
var=$(((100/24)*24))
even if I try to use bc:
var=$(bc <<< "scale=100;100/24*24")
I get something like this:
99.99999999999999999999999999999999999999999999999999999999999999999
99999999999999999999999999999999984;
How to let make the program count the correct way? So that I could get the same values as from the calculator?
This is the result of rounding, to integers (100/24 -> 4 in bash) and floating point (bc lacks a "round" function). See this SO question for related information and links.
It's very hard to provide a general solution here: Most solutions depend on your exact use case, which is probably not what you posted in your question (otherwise you could just put var=100 and move on).
One technique is to reorder the problem (var=$((24*100/24))), which would keep all operations integers.
Another is to multiply by a large offset (var_millionths=$((1000000*(100/24)*24))) and divide out as needed, which would keep enough precision that Bash could round the result well.
Finally, you could (ab)use printf to perform the rounding step for you, because you want the number to be round in base 10 (i.e. when printed):
printf "%.0f\n" $(BC_LINE_LENGTH=0 bc <<< "scale=100;100/24*24")

Arithmetic with variable [duplicate]

This question already has answers here:
How do I use floating-point arithmetic in bash?
(23 answers)
Closed 8 years ago.
I need to perform some arithemic with bash.It goes like this
VariableA = (VariableB-VariableC) / 60
Variable A should be approximated to 2 decimal places
I don't know which one of these is the right answer(Don't have a linux server at hand atm to test)
VariableA = $((VariableB-VariableC)/60)
VariableA = $(((VariableB-VariableC)/))/60)
It would be nice if someone could also help me out about how to round the VariableA to 2 decimal places without using third party tools like bc
The bash itself can compute only integer values, so if you need to use a fixed number of decimals, you can shift your decimal point (it's like computing in cents instead of dollars or euros). Then only at the output you need to make sure there's a . before the last two digits of your number:
a=800
b=300
result=$((a*100/b)) # factor 100 because of division!
echo "${result:0:-2}.${result: -2}"
will print 2.66.
If you want to make computations in floating points, you should use a tool like bc to do that for you:
bc <<<'scale=2; 8.00/3.00'
will print out 2.66.

Bash - stripping of the last digits of a number - which one is better in terms of semantic?

Consider a this string containing an integer
nanoseconds=$(date +%s%N)
when I want to strip off the last six characters, what would be semantically better?
Stripping just the characters off the string
nanoseconds=$(date +%s%N)
milliseconds=${nanoseconds%??????}
or dividing the value by 1000000
milliseconds=$((nanoseconds / 1000000))
EDIT
Sry for not being clear. It's basically for doing a conversion from nanoseconds to milliseconds. I think I answered my own question...
Both are equivalent, but in general I would consider the former method to be safer. The first method is explicit and does precisely what you want to do: to remove a substring from the back of the string.
The other one is a mathematical operation that relies on correct rounding. Although I cannot imagine where it would fail, I would prefer the first method.
Unless, of course, what you really want is not stripping the last three characters but dividing by 1000 :-)
Post scriptum: hah, of course I know where it would fail. Let value="123". ${value%???} strips the last three digits, as intended, leaving an empty string. $(( value / 1000 )) results in value equal to "0" (a string of length of 1).
EDIT: since we know now that it is not about stripping characters, but rounding, clearly dividing by 1000 is the correct way of approaching the problem :-)
The clearest method when strings are involved is probably string subscription in shells that support it.
s=$(LC_TIME=C date +%s.%N) s=${s::-3}
Fortunately it appears GNU date at least defaults to zero-padding for %N, so division should be reliable. (note that both of these methods are truncation, not rounding).
(( s=(10#$(LC_TIME=C date +%s%N))/1000 ))
If you want to round, you can do a bit better than these using printf
printf -v milliseconds %.6f "$(LC_TIME=C date +%s.%N)"
ksh93's printf supports %N so there's no need for date. The conversion can be automatic. If you have (a modern) ksh available you should definitely use it.
typeset -T MsTime=(
typeset -lF6 .=0
function get {
((.sh.value=$(LC_TIME=C printf '%(%s.%N)T')))
}
)
MsTime milliseconds
print -r "$milliseconds"

How to do high precision float point arithmetics in mathematica

In Mma, for example, I want to calculate
1.0492843824838929890231*0.2323432432432432^3
But it does not show the full precision. I tried N or various other functions but none seemed to work. How to achieve this? Many thanks.
When you specify numbers using decimal point, it takes them to have MachinePrecision, roughly 16 digits, hence the results typically have less than 16 meaningful digits. You can do infinite precision by using rational/algebraic numbers. If you want finite precision that's better than default, specify your numbers like this
123.23`100
This makes Mathematica interpret the number as having 100 digits of precision. So you can do
ans=1.0492843824838929890231`100*0.2323432432432432`100^3
Check precision of the final answer using Precision
Precision[ans]
Check tutorial/ArbitraryPrecisionNumbers for more details
You may do:
r[x_]:=Rationalize[x,0];
n = r#1.0492843824838929890231 (r#0.2323432432432432)^3
Out:
228598965838025665886943284771018147212124/17369643723462006556253010609136949809542531
And now, for example
N[n,100]
0.01316083216659453615093767083090600540780118249299143245357391544869\
928014026433963352910151464006549
Sometimes you just want to see more of the machine precision result. These are a few methods.
(1) Put the cursor at the end of the output line, and press Enter (not on the numeric keypad) to copy the output to a new input line, showing all digits.
(2) Use InputForm as in InputForm[1.0/7]
(3) Change the setting of PrintPrecision using the Options Inspector.

Resources