|
namejm
荣誉版主
       batch fan
积分 5226
发帖 1737
注册 2006-3-10 来自 成都
状态 离线
|
『楼 主』:
求最大公约数和最小公倍数
使用 LLM 解释/回答一下
看到lxmxn在玩求素数的批处理,我也玩一个,不过这个难度要低得多,没有对输入作容错检查,不保证结果是否发生溢出错误,仅作为茶余饭后的无聊之作:
@echo off
setlocal enabledelayedexpansion
:begin
cls
set flag=
set num1=
set num2=
set /p num1= 请输入第一个数:
set /p num2= 请输入第二个数:
if %num1% leq %num2% (set min=%num1%) else set min=%num2%
:: 此 if 语句可以改为 if %num1% gtr %num2% set /a num1=%num2%,num2=%num1% ,
:: 以达到减少变量数目的目的,则下一句 for 中的 %min% 就得相应地修改为 %num1%
for /l %%i in (%min%,-1,2) do (
set GCD=%%i
set /a mod1=%num1%%%%%i
set /a mod2=%num2%%%%%i
if !mod1! equ 0 if !mod2! equ 0 set flag=1&goto end
)
:end
if defined flag (
set /a LCM=%num1%/%GCD%*%num2%
echo %num1% 和 %num2% 的最大公约数是 %GCD%,最小公倍数是 !LCM!
) else (
set /a LCM=%num1%*%num2%
echo %num1% 和 %num2% 最大公约数为1,最小公倍数是 !LCM!
)
pause
goto begin
Last edited by namejm on 2007-1-24 at 02:59 PM ]
I saw that lxmxn was playing with a batch script to find prime numbers, so I also played one, but this one is much easier. There is no fault tolerance check for input, and it is not guaranteed that the result will not have an overflow error. It is just a boring thing for leisure:
@echo off
setlocal enabledelayedexpansion
:begin
cls
set flag=
set num1=
set num2=
set /p num1= Please enter the first number:
set /p num2= Please enter the second number:
if %num1% leq %num2% (set min=%num1%) else set min=%num2%
:: This if statement can be changed to if %num1% gtr %num2% set /a num1=%num2%,num2=%num1%,
:: to reduce the number of variables, then the next %min% in the for statement has to be modified accordingly to %num1%
for /l %%i in (%min%,-1,2) do (
set GCD=%%i
set /a mod1=%num1%%%%%i
set /a mod2=%num2%%%%%i
if !mod1! equ 0 if !mod2! equ 0 set flag=1&goto end
)
:end
if defined flag (
set /a LCM=%num1%/%GCD%*%num2%
echo The greatest common divisor of %num1% and %num2% is %GCD%, and the least common multiple is !LCM!
) else (
set /a LCM=%num1%*%num2%
echo The greatest common divisor of %num1% and %num2% is 1, and the least common multiple is !LCM!
)
pause
goto begin
Last edited by namejm on 2007-1-24 at 02:59 PM ]
|

尺有所短,寸有所长,学好CMD没商量。
考虑问题复杂化,解决问题简洁化。 |
|
2007-1-24 13:35 |
|
|
willsion
高级用户
   
积分 793
发帖 312
注册 2004-9-2
状态 离线
|
|
2007-1-24 23:14 |
|
|
ccwan
金牌会员
     
积分 2725
发帖 1160
注册 2006-9-23 来自 河北廊坊
状态 离线
|
『第 3 楼』:
使用 LLM 解释/回答一下
兄的代码确实精彩,我有一点小疑问,两个数的最大公约数可以是1啊,为什么要显示没有最大公约数呢?在数学中,如果两个数是互质数,那么,它们的最大公约数就是1。
附上一段不用for语句的代码
@echo off
set/p a=输入第一个数
set/p b=输入第二个数
set/a ab=%a%*%b%
cls&echo.&echo/&echo\
echo %a% 和 %b% 的 最大公约数 最小公倍数
if %a% lss %b% goto restart
:loop
set/a num_=%a%%%%b%
if %num_% gtr 0 set/a a=%b%&set/a b=%num_%&goto loop
goto show
:restart
set a=%b%&set b=%a%
goto :loop
:show
set/a num=%ab%/%b%
echo %b% %num%
pause>nul
Last edited by ccwan on 2007-1-25 at 06:38 AM ]
Brother's code is really wonderful. I have a small question. The greatest common divisor of two numbers can be 1. Why display that there is no greatest common divisor? In mathematics, if two numbers are coprime, then their greatest common divisor is 1.
Attached is a piece of code that does not use the for statement
@echo off
set/p a=Enter the first number
set/p b=Enter the second number
set/a ab=%a%*%b%
cls&echo.&echo/&echo\
echo %a% and %b%'s Greatest Common Divisor Least Common Multiple
if %a% lss %b% goto restart
:loop
set/a num_=%a%%%%b%
if %num_% gtr 0 set/a a=%b%&set/a b=%num_%&goto loop
goto show
:restart
set a=%b%&set b=%a%
goto :loop
:show
set/a num=%ab%/%b%
echo %b% %num%
pause>nul
Last edited by ccwan on 2007-1-25 at 06:38 AM ]
|

三人行,必有吾师焉。 学然后知不足,教然后知困,然后能自强也。 |
|
2007-1-25 01:58 |
|
|
namejm
荣誉版主
       batch fan
积分 5226
发帖 1737
注册 2006-3-10 来自 成都
状态 离线
|
『第 4 楼』:
使用 LLM 解释/回答一下
Re ccwan 『第 3 楼』:
sorry,基本概念没有记好,犯了低级错误。
你的代码通过辗转求余的方法来计算最大公约数,确实是个比较好的思路,并且速度比我的要快得多,比如用52317和75569来测试,你的代码转瞬间就求出了最大公约数(虽然求最小公倍数的时候出错了),而我的要跑上10S左右才能算出来。
不过我的代码在计算最小公倍数的时候,能处理的数字范围比你的要大一点(你的代码稍微修改一下就可以了),因为你的是通过先把两个数字相乘然后再除以最大公约数来获得,而我的是先把两个数除以最大公约数之后再乘以最大公约数来获得——其实在计算最小公倍数的时候,我有点机械了,代码还可以精简一下,即先除以最大公约数之后再乘以另外一个数。
另外,你的 set/a num2=%a%%%b% 这条语句,其实是钻了set /a运算的空子,不知是你有意为之还是没注意到:在 set /a 运算中,参与运算的变量可以直接用变量名而无须使用百分号对来引用。如果按照一般的理解,这条语句的意思是 %a% 和 %b% 做 % 运算,可是批处理中的 set/a 并没有 % 这个运算符(虽然CMD下有 % 运算符号,但是批处理中的预处理机制并不会把单个的 % 识别为模运算符),而实际上,运算是按照 %% 来操作的,可能的过程是:CMD预处理机制认为 %% 的优先级高于百分号对的引用,从而先扩展模运算符再处理变量的引用,而此时为 %a 模 b%,在 set /a 运算中,找不到变量 a 模 b,从而抛弃前后百分号,变成用 a的值 模 b的值。这个过程仅为推测,不一定正确。建议你把这条语句改成 set/a num2=a%%b 或者 set/a num2=%a%%%%b% ,以避免造成误解。
Last edited by namejm on 2007-1-24 at 04:00 PM ]
Re ccwan 『Post #3』:
sorry, basic concepts were not remembered well, and a junior mistake was made.
Your code uses the method of successive division to calculate the greatest common divisor, which is indeed a good idea, and the speed is much faster than mine. For example, when testing with 52317 and 75569, your code instantly finds the greatest common divisor (although there was an error when calculating the least common multiple), while mine takes about 10 seconds to calculate.
However, my code can handle a larger range of numbers when calculating the least common multiple than yours (your code can be modified a bit). Because yours is to first multiply the two numbers and then divide by the greatest common divisor, while mine is to first divide the two numbers by the greatest common divisor and then multiply by the greatest common divisor - actually, I was a bit mechanical when calculating the least common multiple, and the code can be streamlined, that is, first divide by the greatest common divisor and then multiply by the other number.
In addition, your set/a num2=%a%%%b% statement actually takes advantage of the loophole in set /a operation. I don't know if you did it on purpose or didn't notice: in set /a operation, the variables involved in the operation can be directly referenced by using the variable name without using percent pairs. According to the general understanding, the meaning of this statement is that %a% and %b% do % operation, but there is no % operator in batch processing's set/a (although there is a % operator in CMD, the preprocessing mechanism in batch processing will not recognize a single % as a modulus operator). In fact, the operation is performed according to %% operation. The possible process is: the CMD preprocessing mechanism thinks that the priority of %% is higher than the reference of percent pairs, so it expands the modulus operator first and then processes the reference of variables. At this time, it is %a modulo b%. In the set /a operation, the variable a modulo b is not found, so the percent signs before and after are discarded, and it becomes using the value of a modulo the value of b. This process is only a speculation and may not be correct. It is suggested that you change this statement to set/a num2=a%%b or set/a num2=%a%%%%b% to avoid misunderstanding.
Last edited by namejm on 2007-1-24 at 04:00 PM ]
|

尺有所短,寸有所长,学好CMD没商量。
考虑问题复杂化,解决问题简洁化。 |
|
2007-1-25 03:08 |
|
|
ccwan
金牌会员
     
积分 2725
发帖 1160
注册 2006-9-23 来自 河北廊坊
状态 离线
|
『第 5 楼』:
使用 LLM 解释/回答一下
谢谢jm兄的指点,我的考虑是:set/a num2=%a%%%b% 这条语句中若根据兄的意思,改为a%%b的话,cmd运算中会当作a%b,然后查找a,b的值去运算;而我的代码在cmd中会直接取a的值,然后模b,若a=8,则运算式为set/a num2=8%b,这样减少了一个数值的查找,并不会出现错误。
这可以在cmd下通过实验看到。
对于兄的异议,这正是我知识匮乏的结果,不能从根本上了解它的运行机制。我还是在这里改为set/a num2=%a%%%%b%吧,这样比较好理解。
Last edited by ccwan on 2007-1-25 at 03:50 AM ]
Thanks to brother jm's guidance, my consideration is: In the statement `set/a num2=%a%%%b%`, if it is changed to `a%%b` according to brother's meaning, in cmd operation, it will be regarded as `a%b`, and then the values of a and b will be searched to calculate; while my code in cmd will directly take the value of a, and then take modulo b. If a = 8, the operation formula is `set/a num2=8%b`, which reduces the search for one value and will not have an error.
This can be seen through experiments under cmd.
For brother's objection, this is exactly the result of my lack of knowledge, and I can't fundamentally understand its operation mechanism. I still change it here to `set/a num2=%a%%%%b%`, which is easier to understand.
Last edited by ccwan on 2007-1-25 at 03:50 AM ]
|

三人行,必有吾师焉。 学然后知不足,教然后知困,然后能自强也。 |
|
2007-1-25 03:32 |
|
|
20080610
初级用户
 
积分 83
发帖 34
注册 2006-11-24
状态 离线
|
|
2007-1-25 04:05 |
|
|
namejm
荣誉版主
       batch fan
积分 5226
发帖 1737
注册 2006-3-10 来自 成都
状态 离线
|
『第 7 楼』:
使用 LLM 解释/回答一下
呵呵,原来已经有人做过了啊,没仔细搜索旧帖,造成了内容重复,罪过。
不过那个帖子是作为查错帖出现的,而这里提供的是另外的一种思路,合并主题似乎有点不合适,暂时不合并了,看看还有没有其他比较另类的算法或深入的分析出现。
Hehe, it turns out someone has already done it. I didn't search the old posts carefully enough, resulting in duplicate content. Guilty.
But that post appeared as a post for checking errors, and what's provided here is another kind of idea. It seems inappropriate to merge the topics for now. Let's see if there are other relatively unconventional algorithms or in-depth analyses emerging.
|

尺有所短,寸有所长,学好CMD没商量。
考虑问题复杂化,解决问题简洁化。 |
|
2007-1-25 04:22 |
|
|
pengfei
银牌会员
    
积分 1218
发帖 485
注册 2006-7-21 来自 湖南.娄底
状态 离线
|
『第 8 楼』:
使用 LLM 解释/回答一下
namejm兄和ccwan兄写的代码很不错, 辗转相除法的确是求最大公约数和公倍数的最佳算法, 也是平时最常采用的方法.
它在求公约数时, 将被除数和余数分别赋给下一步将要运算的除数和被除数, 直到余数为0止.
@echo off
set /p x=请输入第一个数:
set /p y=请输入第二个数:
set /a m=x,n=y
if %x% lss %y% set /a x=%y%,y=%x%
:go
set /a r=x%%y,x=y,y=r
if %y% neq 0 goto go
set /a p=m*n,z=p/x
echo %m% 和 %n%的最大公约数为:%x%
echo %m% 和 %n%的最小公倍数为:%z%
pause
Last edited by pengfei on 2007-1-25 at 10:32 AM ]
Brother namejm and Brother ccwan wrote very good code. The Euclidean algorithm is indeed the best algorithm for finding the greatest common divisor and common multiple, and it is also the most commonly used method in daily life.
When finding the common divisor, it assigns the dividend and the remainder to the divisor and dividend for the next operation respectively until the remainder is 0.
@echo off
set /p x=Please enter the first number:
set /p y=Please enter the second number:
set /a m=x,n=y
if %x% lss %y% set /a x=%y%,y=%x%
:go
set /a r=x%%y,x=y,y=r
if %y% neq 0 goto go
set /a p=m*n,z=p/x
echo The greatest common divisor of %m% and %n% is:%x%
echo The least common multiple of %m% and %n% is:%z%
pause
Last edited by pengfei on 2007-1-25 at 10:32 AM ]
|

业精于勤而荒于嬉,形成于思而毁于随。 |
|
2007-1-25 05:29 |
|
|
lzmyst
新手上路

积分 19
发帖 10
注册 2005-12-13
状态 离线
|
『第 9 楼』:
使用 LLM 解释/回答一下
暂时还不能完全理解,先COPY下来慢慢看。
Temporarily unable to fully understand, first COPY it down and look at it slowly.
|
|
2007-1-25 06:01 |
|
|
tao0610
高级用户
    朦胧的世界
积分 579
发帖 218
注册 2006-10-24
状态 离线
|
『第 10 楼』:
使用 LLM 解释/回答一下
....
@echo off&setlocal enabledelayedexpansion
set /p num1= 请输入第一个数:
set /p num2= 请输入第二个数:
if %num1% geq %num2% (set g=%num1%&set l=%num2%) else set g=%num2%&set l=%num1%
:loop
set/a b+=g,mod=b%%l
if not %mod%==0 goto loop
set/a a=g*l/b
echo %num1% 和 %num2% 的最大公约数是 %a%,最小公倍数是 %b%
pause
....
@echo off&setlocal enabledelayedexpansion
set /p num1= Please enter the first number:
set /p num2= Please enter the second number:
if %num1% geq %num2% (set g=%num1%&set l=%num2%) else set g=%num2%&set l=%num1%
:loop
set/a b+=g,mod=b%%l
if not %mod%==0 goto loop
set/a a=g*l/b
echo The greatest common divisor of %num1% and %num2% is %a%, and the least common multiple is %b%
pause
|

认识自己,降伏自己,改变自己,才能改变别人! |
|
2007-1-25 06:07 |
|