in reply to Convert seconds into a formatted ddd:hh:mm:ss string
OK there it is. I used "best" and "best_int" as the methods I've decided best fits my needs. So here are the results of running this code:#!/opt/perl5/bin/perl -w use strict; sub best_int { use integer; my $s = shift; return sprintf ":%02d", $s if $s < 60; my $m = $s / 60; $s = $s % 60; return sprintf "%02d:%02d", $m, $s if $m < 60; my $h = $m / 60; $m %= 60; return sprintf "%02d:%02d:%02d", $h, $m, $s if $h < 24; my $d = $h / 24; $h %= 24; return sprintf "%d:%02d:%02d:%02d", $d, $h, $m, $s; } sub best { my $s = shift; return sprintf ":%02d", $s if $s < 60; my $m = $s / 60; $s = $s % 60; return sprintf "%02d:%02d", $m, $s if $m < 60; my $h = $m / 60; $m %= 60; return sprintf "%02d:%02d:%02d", $h, $m, $s if $h < 24; my $d = $h / 24; $h %= 24; return sprintf "%d:%02d:%02d:%02d", $d, $h, $m, $s; } sub husker { my ($out_m, $hold_sec, $out_str, $in_sec, $out_d, $out_h, $out_s); $in_sec=shift; $hold_sec = $in_sec; $out_d = $in_sec / 86400; $in_sec = $in_sec % 86400; $out_h = $in_sec / 3600; $in_sec = $in_sec % 3600; $out_m = $in_sec / 60; $in_sec = $in_sec % 60; $out_s = $in_sec; if ($out_d > 0) { $out_str = sprintf "%0.f:%0.2u:%0.2u:%0.2u", $out_d, $out_h, $ +out_m, $out_s; } elsif ($out_h > 0) { $out_str = sprintf " %0.2u:%0.2u:%0.2u", $out_h, $out_m, $out_ +s; } elsif ($out_m > 0) { $out_str = sprintf "%0.2u:%0.2u", $out_m, $out_s; } else { $out_str = sprintf ":%0.2u", $out_s; } return $out_str; } sub adam { use integer; my $sec = shift; return ":0$sec" if $sec < 10; return ":$sec" if $sec < 60; my $min = $sec / 60, $sec %= 60; $sec = "0$sec" if $sec < 10; return "$min:$sec" if $min < 60; my $hr = $min / 60, $min %= 60; $min = "0$min" if $min < 10; return "$hr:$min:$sec" if $hr < 24; my $day = $hr / 24, $hr %= 24; $hr = "0$hr" if $hr < 10; return "$day:$hr:$min:$sec"; } sub blaise { my $sec = shift; my @str; use integer; for my $d (60, 60, 24) { my $m = $sec % $d; $sec /= $d; $m = '0'.$m if $m < 10; unshift @str, $m; } return "$sec:".join ":",@str; } sub fund { my $t = shift; my @out=reverse ($t%60, ($t/=60)%60, ($t/=60)%24, ($t/=24) ); my $out=sprintf "%03d:%02d:%02d:%02d", @out; $out=~s/^0+:|00://g; return $out; } sub ncw { my $seconds = shift; my $string = join ":", map { sprintf "%02d", $_} (gmtime($seconds) +)[7,2,1,0]; $string=~s/\G00://g; return $string; } my ($s, $i, $x, $m, $a, $r, $f, $b, $n); for $s (1,5,100,10000,1000000,100000000, 3000000000) { $i=best_int($s); $m=husker($s); $a=adam($s); $b=blaise($s); $f=fund ($s); $n=ncw($s); $x=best($s); write(); } format STDOUT_TOP= seconds best_int best husker <P> ------------- ------------- -------------- -------------<P> + -------------- -------------- -------------- -------------- +- . format STDOUT = @############ @>>>>>>>>>>>> @>>>>>>>>>>>>> @>>>>>>>>>>>>> +@>>>>>>>>>>>>> @>>>>>>>>>>>>> @>>>>>>>>>>>>> @>>>>>>>>>>>>>> $s,$i,$x,$m,$a,$b,$f,$n .
| Seconds | best_int | best | husker | adam | Blaise | fund | ncw |
| 1 | :01 | :01 | :01 |
:01 | 0:00:00:01 | 01 | 01 |
| 5 | :05 | :05 | :05 | :05 | 0:00:00:05 | 05 | 05 |
| 100 | 01:40 | 01:40 | 01:40 | 1:40 | 0:00:01:40 | 01:40 | 01:40 |
| 10000 | 02:46:40 | 02:46:40 | 02:46:40 | 2:46:40 | 0:02:46:40 | 02:46:40 | 02:46:40 |
| 1000000 | 11:13:46:40 | 11:13:46:40 | 11:13:46:40 | 11:13:46:10 | 11:13:46:10 | 11:13:46:10 | 11:13:46:10 |
| 100000000 | 1157:09:46:40 | 1157:09:46:40 | 1157:09:46:40 | 1157:09:46:40 | 1157:09:46:40 | 1157:09:46:40 | 61:09:46:40 |
| 300000000 | :-1294967296 | 34722:05:20:00 | :4294967280 |
:03000000000 | -14988:0-1:0-8 | 34722:05:20:00 | 352:22:51:44 |
All the other differences are formatting. The formatting I was aiming for are displayed in "best". Agreeing with merlyn about using sprintf, it looks like that's really the only way to get exactly the formatting I'm wanting. Using regexp's and substitution just doesn't catch it (but then I'm no regexp expert). However, this is minor, because like I said the most important thing is that everyone was getting the right answer until the inputs became very large, and knowing what we know about integers, they fail in ways we expect.
OK let's look at performance. There are some interesting comments to be made about how these perform I think. To be thorough, I did multiple benchmarks.. The benchmark platform is an HP9000 Model H50, which is really an old dog .. it's a 96-Mhz PA-RISC 7100. Perl is version 5.005_03.
What do we notice?Benchmark: timing 100000 iterations of adam, best, best_int, blaise, f +und, husker, ncw... TIME converted is 1 seconds... adam: 2 wallclock secs ( 2.52 usr + -0.01 sys = 2.51 CPU) best: 4 wallclock secs ( 3.61 usr + 0.00 sys = 3.61 CPU) best_int: 3 wallclock secs ( 3.26 usr + 0.01 sys = 3.27 CPU) blaise: 22 wallclock secs (20.81 usr + 0.03 sys = 20.84 CPU) fund: 15 wallclock secs (14.84 usr + 0.02 sys = 14.86 CPU) husker: 14 wallclock secs (12.82 usr + 0.01 sys = 12.83 CPU) ncw: 21 wallclock secs (20.94 usr + 0.03 sys = 20.97 CPU) TIME converted is 5 seconds... adam: 3 wallclock secs ( 2.53 usr + 0.00 sys = 2.53 CPU) best: 4 wallclock secs ( 3.61 usr + 0.01 sys = 3.62 CPU) best_int: 3 wallclock secs ( 3.27 usr + 0.01 sys = 3.28 CPU) blaise: 21 wallclock secs (20.74 usr + 0.03 sys = 20.77 CPU) fund: 15 wallclock secs (14.75 usr + 0.02 sys = 14.77 CPU) husker: 18 wallclock secs (12.93 usr + 0.03 sys = 12.96 CPU) ncw: 22 wallclock secs (20.95 usr + 0.03 sys = 20.98 CPU) TIME converted is 100 seconds... adam: 6 wallclock secs ( 5.91 usr + 0.01 sys = 5.92 CPU) best: 7 wallclock secs ( 6.22 usr + 0.02 sys = 6.24 CPU) best_int: 5 wallclock secs ( 5.67 usr + 0.00 sys = 5.67 CPU) blaise: 21 wallclock secs (19.98 usr + 0.01 sys = 19.99 CPU) fund: 15 wallclock secs (14.22 usr + 0.00 sys = 14.22 CPU) husker: 13 wallclock secs (12.97 usr + 0.00 sys = 12.97 CPU) ncw: 22 wallclock secs (20.91 usr + 0.04 sys = 20.95 CPU) TIME converted is 10000 seconds... adam: 9 wallclock secs ( 8.76 usr + 0.02 sys = 8.78 CPU) best: 9 wallclock secs ( 8.64 usr + 0.01 sys = 8.65 CPU) best_int: 8 wallclock secs ( 7.90 usr + 0.01 sys = 7.91 CPU) blaise: 20 wallclock secs (19.19 usr + 0.01 sys = 19.20 CPU) fund: 14 wallclock secs (13.60 usr + 0.02 sys = 13.62 CPU) husker: 13 wallclock secs (13.09 usr + 0.02 sys = 13.11 CPU) ncw: 21 wallclock secs (20.39 usr + 0.03 sys = 20.42 CPU) TIME converted is 1000000 seconds... adam: 13 wallclock secs (12.06 usr + 0.02 sys = 12.08 CPU) best: 11 wallclock secs (10.74 usr + 0.00 sys = 10.74 CPU) best_int: 10 wallclock secs ( 9.87 usr + 0.01 sys = 9.88 CPU) blaise: 19 wallclock secs (18.79 usr + 0.01 sys = 18.80 CPU) fund: 18 wallclock secs (12.27 usr + 0.03 sys = 12.30 CPU) husker: 13 wallclock secs (13.34 usr + 0.01 sys = 13.35 CPU) ncw: 19 wallclock secs (18.63 usr + 0.01 sys = 18.64 CPU) TIME converted is 100000000 seconds... adam: 14 wallclock secs (13.20 usr + 0.02 sys = 13.22 CPU) best: 11 wallclock secs (10.92 usr + 0.02 sys = 10.94 CPU) best_int: 11 wallclock secs (10.05 usr + 0.01 sys = 10.06 CPU) blaise: 19 wallclock secs (19.32 usr + 0.03 sys = 19.35 CPU) fund: 13 wallclock secs (12.24 usr + 0.02 sys = 12.26 CPU) husker: 14 wallclock secs (13.38 usr + 0.02 sys = 13.40 CPU) TIME converted is 3000000000 seconds... best: 11 wallclock secs (10.71 usr + 0.03 sys = 10.74 CPU) fund: 13 wallclock secs (12.07 usr + 0.02 sys = 12.09 CPU)
fundflow's algorithm actually seems to get FASTER for larger numbers. Might that be because the regex substitution at the end has less work to do with a longer output string...?
What can we learn from these results?
Some algorithms do the same amount of work regardless of the TIME value, while others quit once they know they have the final answer. While the former algorithms are "purer" from an algorithmic viewpoint, the latter algorithms are more effecient, certainly.
Integer math is faster than floating point math, with the tradeoff being precision.
Using sprintf to truncate floating point numbers seems to be less efficient that doing integer math in the first place. Further, using sprintf seems to give you more control than over regexp evaluation, or building your own strings by hand, and doesn't seem to be a big performance hit over those two methods, if it all.
Anyway, this has been a long post. I hope you enjoyed it. :) Wait until you see my next submission! LOL
Lastly, thanks to everyone who submitted code. It's a learning experience for me all the time.
|
|---|