Talk:Least common multiple: Difference between revisions
Content added Content deleted
(→(REXX) versions 1 and 2 compared: moved to discussion from the main page.) |
|||
Line 34: | Line 34: | ||
: Visibility of task description formula restored [[User:Hout|Hout]] ([[User talk:Hout|talk]]) 23:05, 26 October 2016 (UTC) |
: Visibility of task description formula restored [[User:Hout|Hout]] ([[User talk:Hout|talk]]) 23:05, 26 October 2016 (UTC) |
||
===(REXX) versions 1 and 2 compared=== |
|||
(─── Moved here from the main page, as I (REXX version 1's author) thought it wasn't suitable being there, and it should |
|||
instead belong here on the discussion page. ───) -- [[User:Gerard Schildberger|Gerard Schildberger]] ([[User talk:Gerard Schildberger|talk]]) 00:55, 3 October 2017 (UTC) |
|||
(Below is from the REXX version 2's author.) |
|||
----- |
|||
The ''(performance) improvement'' of version 2 is due to the different argument handling at the cost of less ''freedom'' of argument specification (you must use lcm2(a,b,c) instead of the ''possible'' lcm1(a b,c). Consider, however, lcm1(3 -4, 5) which, of course, won't work as possibly intended. |
|||
<br>The performance improvement is more significant with ooRexx than with Regina. |
|||
<br> ''Note:'' $ in version 1 was replaced by d in order to adapt it for this test with ooRexx. |
|||
<lang rexx>Parse Version v |
|||
Say 'Version='v |
|||
Call time 'R' |
|||
Do a=0 To 100 |
|||
Do b=0 To 100 |
|||
Do c=0 To 100 |
|||
x1.a.b.c=lcm1(a,b,c) |
|||
End |
|||
End |
|||
End |
|||
Say 'version 1' time('E') |
|||
Call time 'R' |
|||
Do a=0 To 100 |
|||
Do b=0 To 100 |
|||
Do c=0 To 100 |
|||
x2.a.b.c=lcm2(a,b,c) |
|||
End |
|||
End |
|||
End |
|||
Say 'version 2' time('E') |
|||
cnt.=0 |
|||
Do a=0 To 100 |
|||
Do b=0 To 100 |
|||
Do c=0 To 100 |
|||
If x1.a.b.c=x2.a.b.c then cnt.0ok=cnt.0ok+1 |
|||
End |
|||
End |
|||
End |
|||
Say cnt.0ok 'comparisons ok' |
|||
Exit |
|||
/*----------------------------------LCM subroutine----------------------*/ |
|||
lcm1: procedure; d=strip(arg(1) arg(2)); do i=3 to arg(); d=d arg(i); end |
|||
parse var d x d /*obtain the first value in args.*/ |
|||
x=abs(x) /*use the absolute value of X. */ |
|||
do while d\=='' /*process the rest of the args. */ |
|||
parse var d ! d; !=abs(!) /*pick off the next arg (ABS val)*/ |
|||
if !==0 then return 0 /*if zero, then LCM is also zero.*/ |
|||
x=x*!/gcd1(x,!) /*have GCD do the heavy lifting.*/ |
|||
end /*while*/ |
|||
return x /*return with LCM of arguments.*/ |
|||
/*----------------------------------GCD subroutine----------------------*/ |
|||
gcd1: procedure; d=strip(arg(1) arg(2)); do j=3 to arg(); d=d arg(j); end |
|||
parse var d x d /*obtain the first value in args.*/ |
|||
x=abs(x) /*use the absolute value of X. */ |
|||
do while d\=='' /*process the rest of the args. */ |
|||
parse var d y d; y=abs(y) /*pick off the next arg (ABS val)*/ |
|||
if y==0 then iterate /*if zero, then ignore the value.*/ |
|||
do until y==0; parse value x//y y with y x; end |
|||
end /*while*/ |
|||
return x /*return with GCD of arguments.*/ |
|||
lcm2: procedure |
|||
x=abs(arg(1)) |
|||
do k=2 to arg() While x<>0 |
|||
y=abs(arg(k)) |
|||
x=x*y/gcd2(x,y) |
|||
end |
|||
return x |
|||
gcd2: procedure |
|||
x=abs(arg(1)) |
|||
do j=2 to arg() |
|||
y=abs(arg(j)) |
|||
If y<>0 Then Do |
|||
do until z==0 |
|||
z=x//y |
|||
x=y |
|||
y=z |
|||
end |
|||
end |
|||
end |
|||
return x</lang> |
|||
{{out}} |
|||
Output of rexx lcmt and regina lcmt cut and pasted together: |
|||
<pre>Version=REXX-ooRexx_4.2.0(MT)_32-bit 6.04 22 Feb 2014 |
|||
Version=REXX-Regina_3.9.0(MT) 5.00 16 Oct 2014 |
|||
version 1 29.652000 version 1 23.821000 |
|||
version 2 10.857000 version 2 21.209000 |
|||
1030301 comparisons ok 1030301 comparisons ok</pre> |
|||
----- |
|||
I «[[User:Gerard Schildberger|Gerard Schildberger]] ([[User talk:Gerard Schildberger|talk]]) 00:55, 3 October 2017 (UTC)» generally don't like to compare REXX program examples for speed unless a version has increased |
|||
functionality (or options), and there is a sufficient increase in speed to warrant including another |
|||
(hopefully more advanced) REXX program. The exception to this is when a better program |
|||
version is much faster than another, usually in the order of a magnitude, or in the case where the |
|||
program runs a significant amount of time (elapsed or CPU) ─── for instance, in minutes. |
|||
From what I understand of the (or ''a'') Rosetta Code policy is that language speed comparisons of two |
|||
different languages (such as ooRexx and REXX) are discouraged. If not different languages, |
|||
then at least they are of two different dialects. We're not here on Rosetta Code to compare |
|||
how fast one language is to another. |
|||
For computing the '''LCM''', unless it is invoked a significant number of times, it doesn't matter |
|||
that much if one is 10% slower than another. |
|||
One bad thing about measuring two different programming examples (especially if they were |
|||
written by two different authors), is that when one version changes, will the other |
|||
person then re─run their comparison and re─edit the results of the comparison runs? |
|||
This has been shown to be demonstratively not be the case. |
|||
In particular, the 1<sup>st</sup> REXX version (mine) had it's '''LCM''' function updated a while ago with |
|||
a faster version (by me), but the comparison evaluation used the older REXX version. Instead of the |
|||
2<sup>nd</sup> version being faster by about 10%, it was now slower by about 65% (or some |
|||
such numbers, see below for the latest comparisons). |
|||
I would prefer this whole comparison stuff be struck (by a Rosetta Code administrator) from this |
|||
task's discussion page as it solves no worthwhile purpose that is in compliance with Rosetta Code |
|||
policy. Rosetta Code is for showing how to solve problems and be helpful in comparing |
|||
functionality of computer programming languages. These are my opinions, of course, and may |
|||
not be based in reality. Hopefully, someone with more more authority on RC's policies will |
|||
step in. However, this may be used as a teaching moment. |
|||
Secondly, running (benchmarking) comparative executions is more science than art, there are a lot |
|||
of pitfalls: making sure to use the identical data, not re─writing code (to make a square |
|||
peg to fit into a round hole), one version paying a penalty for initializing/defining variables (a |
|||
big deal in interpretive languages), the obtaining of storage, including/loading ("system") |
|||
subroutines/functions, garbage collection, pollution of memory (pools), the use of caching by |
|||
subsequent execution(s), etc. (or as it is said often elsewhere, too many to be |
|||
listed here). For the above reasons and others, I've extensively re─written the old benchmark program and |
|||
re─run it (for more trials). The results are included here below (after the benchmark |
|||
REXX program). |
|||
The old benchmark program was re─worked considerably, including the removal of comparing results. |
|||
The results should be computed once, and after verification that they produce identical |
|||
results, that part of the code can be elided. Once that removal is done, there is no need to |
|||
pollute the variable pool with over a million ('''101<sup>3</sup>''') individual answers (it |
|||
then becomes an exercise on how efficient the generating/retrieval of variables is). Also, |
|||
the '''do''' loops were optimized to cut down on their overhead, the use of |
|||
'''for''' instead of '''to''' reduces the overhead of the benchmarking |
|||
program, that is, the part of the benchmarking program that is common to the testing of both functions. |
|||
We don't want to have the overhead of the benchmark itself overwhelm what is being measured. |
|||
Added to the benchmark program are options to specify how many trials, and the ('''high''') number |
|||
of invocations of the various (well, only two) '''LCM''' function versions. Also |
|||
added were titles and also more whitespace to make the output easier to read. |
|||
Note that if the '''LCM1''' function is invoked by an alternative invocation, it is |
|||
even faster (see the ''is faster'' note/comment within the REXX code of version |
|||
1 on line sixteen). This is one reason why the REXX version 1 has that |
|||
option (functionality) ─── to allow the user to use whatever form is easier or desirable for them, |
|||
not to mention the invocation form that is faster. |
|||
Also noteworthy is that the PC used for the execution of the benchmark program is an air─gap |
|||
computer (with four cores running under Microsoft's Windows 7) and having no contention with |
|||
any other programs. |
|||
The benchmarking program is: |
|||
<lang rexx>/*REXX program supposedly measures/compares 2 versions of LCM (least common multiplier).*/ |
|||
parse version v; say 'version=' v |
|||
parse arg high trials . |
|||
if high=='' | high=="," then high=101 |
|||
if trials=='' | trials=="," then trials= 10 |
|||
do t=1 for trials |
|||
say |
|||
say center(' trial' right(t, length(trials) )" ", 40, '~') |
|||
call time 'reset' |
|||
do a=0 for high |
|||
do b=0 for high |
|||
do c=0 for high |
|||
answer1=lcm1(a, b, c) /*LCM1(a b c) is faster.*/ |
|||
end /*c*/ |
|||
end /*b*/ |
|||
end /*a*/ |
|||
say ' version 1 took' format( time( 'elapsed'), , 2) "seconds." |
|||
call time 'reset' |
|||
do x=0 for high |
|||
do y=0 for high |
|||
do z=0 for high |
|||
answer2=lcm2(x, y, z) |
|||
end /*z*/ |
|||
end /*y*/ |
|||
end /*x*/ |
|||
say ' version 2 took' format( time( 'elapsed'), , 2) "seconds." |
|||
say |
|||
end /*times*/ |
|||
exit /*stick a fork in it, we're all done. */ |
|||
/*──────────────────────────────────────────────────────────────────────────────────────*/ |
|||
lcm1: procedure; parse arg $,_; $=$ _; do i=3 to arg(); $=$ arg(i); end /*i*/ |
|||
parse var $ x $ /*obtain the first value in args. */ |
|||
x=abs(x) /*use the absolute value of x. */ |
|||
do while $\=='' /*process the remainder of args. */ |
|||
parse var $ ! $; if !<0 then !=-! /*pick off the next arg (abs val).*/ |
|||
if !==0 then return 0 /*if zero, then lcm is also zero. */ |
|||
d=x*! /*calculate part of the lcm here. */ |
|||
do until !==0; parse value x//! ! with ! x |
|||
end /*until*/ /* [↑] this is a short & fast gcd*/ |
|||
x=d%x /*divide the pre calculated value.*/ |
|||
end /*while*/ /* [↑] process subsequent args. */ |
|||
return x /*return with the lcm of the args.*/ |
|||
/*──────────────────────────────────────────────────────────────────────────────────────*/ |
|||
lcm2: procedure |
|||
x=abs(arg(1)) |
|||
do k=2 to arg() while x<>0 |
|||
y=abs(arg(k)) |
|||
x=x*y/gcd2(x,y) |
|||
end |
|||
return x |
|||
gcd2: procedure |
|||
x=abs(arg(1)) |
|||
do j=2 to arg() |
|||
y=abs(arg(j)) |
|||
if y<>0 then do |
|||
do until z==0 |
|||
z=x//y |
|||
x=y |
|||
y=z |
|||
end |
|||
end |
|||
end |
|||
return x</lang> |
|||
{{out|output|text= when using the default input:}} |
|||
<pre> |
|||
version= REXX-Regina_3.9.1(MT) 5.00 5 Apr 2015 |
|||
═══════════════ trial 1 ═══════════════ |
|||
version 1 took 13.35 seconds. |
|||
version 2 took 21.34 seconds. |
|||
═══════════════ trial 2 ═══════════════ |
|||
version 1 took 13.37 seconds. |
|||
version 2 took 21.31 seconds. |
|||
═══════════════ trial 3 ═══════════════ |
|||
version 1 took 13.37 seconds. |
|||
version 2 took 21.33 seconds. |
|||
═══════════════ trial 4 ═══════════════ |
|||
version 1 took 13.35 seconds. |
|||
version 2 took 21.34 seconds. |
|||
═══════════════ trial 5 ═══════════════ |
|||
version 1 took 13.35 seconds. |
|||
version 2 took 21.31 seconds. |
|||
═══════════════ trial 6 ═══════════════ |
|||
version 1 took 13.35 seconds. |
|||
version 2 took 21.33 seconds. |
|||
═══════════════ trial 7 ═══════════════ |
|||
version 1 took 13.37 seconds. |
|||
version 2 took 21.34 seconds. |
|||
═══════════════ trial 8 ═══════════════ |
|||
version 1 took 13.34 seconds. |
|||
version 2 took 21.34 seconds. |
|||
═══════════════ trial 9 ═══════════════ |
|||
version 1 took 13.31 seconds. |
|||
version 2 took 21.25 seconds. |
|||
═══════════════ trial 10 ═══════════════ |
|||
version 1 took 13.32 seconds. |
|||
version 2 took 21.25 seconds. |
|||
</pre> |
|||
-- [[User:Gerard Schildberger|Gerard Schildberger]] ([[User talk:Gerard Schildberger|talk]]) 00:55, 3 October 2017 (UTC) |
|||
----- |