ProgrammingThis forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.
Notices
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
Get a virtual cloud desktop with the Linux distro that you want in less than five minutes with Shells! With over 10 pre-installed distros to choose from, the worry-free installation life is here! Whether you are a digital nomad or just looking for flexibility, Shells can put your Linux machine on the device that you want to use.
Exclusive for LQ members, get up to 45% off per month. Click here for more info.
I have a simple mathematical process i would like to automate with a program of some sort. Maybe even a basic shell script. I would like to have the user specify (or be prompted for) a few variables "A" "B" "C" and "M". Where A,B, and C are values in units of time aka HMS (hh.mmss). And M is in units of MiB.
A+B+C=TT (in HMS, whats the syntax for adding HMS units in the shell?)
A HMS-> / TT HMS-> = AX (unitless factor)
Where "HMS->" (aka HMS OUT) means to convert HMS to a decimal number (unitless).
And repeat for B and C, resulting in AX,BX, and CX.
Then simply:
AX*M=AS (in MiB)
BX*M=BS (in MiB)
CX*M=CS (in MiB)
The desired output would be the numerical values of AS,BS, and CS.
I know theres probably many ways to do this, any suggestions would be helpful. To keep it simple i would prefer a simple bash script if possible.
Note that shell only works in integers, so you'll get rounding or truncation when doing division. If you want floating pt, use the bc tool http://linux.die.net/man/1/bc
are values in units of time aka HMS (hh.mmss). And M is in units of MiB.
A+B+C=TT (in HMS, whats the syntax for adding HMS units in the shell?)
...To keep it simple i would prefer a simple bash script if possible.
The shell (bash) has no data type for time in h:m:s, so if you want to do it with the shell you will have to do all of the management of this datatype yourself.
Actually, nor do most programming languages have an h:m:s datatype inherently, but in some you could happily define an object to have one, and that may make things easier/cleaner.
Also the problem that chrism01 mentions:
Quote:
shell only works in integers... If you want floating pt, use the bc tool
I've never really managed to get on with BC; I'm sure many like it (but not me) and I'd be happier to use a scripting language like python. YMMV, just be aware of deciding 'in advance' (without having thought through all of the issues) of deciding on a particular approach 'to make things simpler' if that approach ends up making things harder.
will convert hh:mm:ss to seconds, provided "hh:" is present & positive (it can of course be 0). Substitute your time value for my "1:20:5" test case. That takes care of your 1st step:
A+B+C=TT
To do decimals for
A HMS-> / TT HMS-> = AX
you must append a 0 (* 10^N) for each decimal place you want. If you want to display the resulting factors, you will need to clean up your output by inserting a decimal point in the correct spot.
You should leave the factors as is for the next step
AX*M=AS (in MiB)
BX*M=BS (in MiB)
CX*M=CS (in MiB)
& divide your results by 10^N.
To me this seems like an easy bash script. I think qualifying the inputs may be more difficult than the arithmetic.
Edit: Changed "1^N" to "10^N"
Last edited by archtoad6; 11-10-2009 at 07:32 AM.
Reason: typo 1^N should be 10^N
will convert hh:mm:ss to seconds, provided "hh:" is present & positive (it can of course be 0). Substitute your time value for my "1:20:5" test case. That takes care of your 1st step:
A+B+C=TT
To do decimals for
A HMS-> / TT HMS-> = AX
you must append a 0 (* 1^N) for each decimal place you want. If you want to display the resulting factors, you will need to clean up your output by inserting a decimal point in the correct spot.
You should leave the factors as is for the next step
AX*M=AS (in MiB)
BX*M=BS (in MiB)
CX*M=CS (in MiB)
& divide your results by 1^N.
To me this seems like an easy bash script. I think qualifying the inputs may be more difficult than the arithmetic.
Your first step for reducing HMS to seconds is great, works perfect, thanks. If i do that, then i can save those values as A,B and C (overwriting original user inputs in HMS). Then, simply sum them to get TT (in seconds is fine). If i leave A and TT in seconds i will still get a unitless factor. As far as decimal places, 12 is fine. Im not sure i understand why or how i need to append to do this, why will it need to be cleaned up exactly? Sorry im not very experienced doing even simple arithmetic in the shell. How would i divide them, then append them (the command/syntax)?
I guess my first step before trying to write a scrip is figuring how to even do it manually in the shell first. So now i can convert HMS to seconds and get TT in seconds. Now i just need to divide each A,B, and C by TT and get a factor to 12 decimal places (AX,BX,CX). Then just multiply AX,BX, and CX by "M", to the nearest whole number is fine.
PS: Is there a source for that "echo $(($(echo "((1:20:5" |sed 's,:,)*60+,g')))" command i could read over, just curious what each piece means exactly (how it works).
Im not sure i understand why or how i need to append to do this, why will it need to be cleaned up exactly? Sorry im not very experienced doing even simple arithmetic in the shell. How would i divide them, then append them (the command/syntax)?
Remember --
Quote:
Originally Posted by chrism01
...Note that shell only works in integers, so you'll get rounding or truncation when doing division. ...
i.e. rounding or truncation errors if you don't append & clean up. Multiply by 10^12 at the beginning & either insert a decimal point or divide by 10^12 at the end.
Quote:
Originally Posted by MaGicMaX
I guess my first step before trying to write a scrip is figuring how to even do it manually in the shell first. So now i can convert HMS to seconds and get TT in seconds.
Definitely a good way to proceed.
Quote:
Originally Posted by MaGicMaX
Now i just need to divide each A,B, and C by TT and get a factor to 12 decimal places (AX,BX,CX). Then just multiply AX,BX, and CX by "M", to the nearest whole number is fine.
As long as you make the correct adjustments for the integer arithmetic limitations of bash.
Quote:
Originally Posted by MaGicMaX
PS: Is there a source for that "echo $(($(echo "((1:20:5" |sed 's,:,)*60+,g')))" command i could read over, just curious what each piece means exactly (how it works).
There are 2, 3, or 4 sources, depending on how you count:
the bash man page -- search for "Arithmetic expansion allows"
the bash man page -- search for "Command substitution allows"
Here are my original & a simpler version colored to highlight the syntax:
Code:
echo $(($(echo "((1:20:5" | sed 's,:,)*60+,g')))
echo $[ `echo "((1:20:5" | sed 's,:,)*60+,g'`] # deprecated but simpler form
Once you have read A, B, or C into your script (& checked them for errors) you can process them from hh:mm:ss into seconds:
Code:
echo $(($(echo "(($A" | sed 's,:,)*60+,g')))
echo $[ `echo "(($A" | sed 's,:,)*60+,g'`] # deprecated but simpler form
We know that either
(hh*60+mm)*60+ss
or, adding a set of mathematically unnecessary, but programatically useful parentheses
((hh)*60+mm)*60+ss
will convert hh:mm:ss into seconds, so the innermost (purple hues) echo adds the 2 necessary leading parentheses to the hh:mm:ss & pipes it into a sed which turns the colons into the right math. Run
Code:
echo "((1:20:5" | sed 's,:,)*60+,g'
to see that this is true.
The Command Substitution
$( ... ) or ` ... `
makes the algebra available to the Arithmetic Expansion
$(( ... )) or
$[ ... ]
The green (1st) echo displays the result of the Arithmetic Expansion, you may not need it in your script.
It's time for you to start working on the commands. Post them & we'll critique them.
Thanks for the detailed response. I think going with a bash scrip might not be as "simple" as i expected. Perhaps going with a programmable (preferably RPN) calculator program (either CLI or GUI) would be an easier way. I planned to automate some other tasks that i may have more trouble with using a bash script. My background in programming calculators began with HP50g, which uses a HP-Basic language. Where a program is basically stored as a global variable and executed as such. A simple one would look like this:
<< A B C + + D 'STO' D "The Answer Is" ->Tag >>
In RPN mode, it would sum A,B and C, store it as a global variable "D" and display the answer on the stack tagged with "The Answer Is". The above program could be saved as global variable "ABCD", and executed by running ABCD. This is the simplicity i was after .
I've since opened another thread regarding suggestions for RPN programmable calculators here.
<OT>
I started w/ a 35 w/ no model # on the case, went on to the 65, the 97, & a 41 -- which languishes needing a battery because there is no room for both it & my phone in my shirt pocket.
So why doesn't HP, alone or w/ Nokia, make the "perfect" engineer/geek phone? Start w/ the shape (from the Wikipedia® article referenced above):
Quote:
... but William Hewlett saw additional opportunities if the desktop calculator could be made small enough to fit into his shirt pocket. He charged his engineers with this exact goal (to the point that they measured his shirt pocket!).
</OT>
Quote:
<< A B C + + D 'STO' D "The Answer Is" ->Tag >>
I hope 'A', 'B', & 'C' aren't your original variables in HMS, because you still need to convert them. Either that or pretend that they are angles in degrees & maybe trick the calculator into adding them correctly. I think it was the conversion that added the complexity that you "choked on". I remember keying HMS #'s into my HPs as "hh0mm0ss" for addition, & using '940', '940940', or '940000' to make the carries work right.
On a pure keystoke RPN calculator the conversion sequence is: HÎ60*M+60*S+ ('Î' is the "Enter" key).
<OT>
I started w/ a 35 w/ no model # on the case, went on to the 65, the 97, & a 41 -- which languishes needing a battery because there is no room for both it & my phone in my shirt pocket.
So why doesn't HP, alone or w/ Nokia, make the "perfect" engineer/geek phone? Start w/ the shape (from the Wikipedia® article referenced above): </OT>
I hope 'A', 'B', & 'C' aren't your original variables in HMS, because you still need to convert them. Either that or pretend that they are angles in degrees & maybe trick the calculator into adding them correctly. I think it was the conversion that added the complexity that you "choked on". I remember keying HMS #'s into my HPs as "hh0mm0ss" for addition, & using '940', '940940', or '940000' to make the carries work right.
On a pure keystoke RPN calculator the conversion sequence is: HÎ60*M+60*S+ ('Î' is the "Enter" key).
In my example i was not assuming the variables to be in HMS, just showing the simple syntax for writing a basic program. HP does have "->HSM" and "HMS->", functions to convert to and out of HMS, but short of that, it can be done manually too (in the program).
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.