为啥程序流控制随机执行
Posted
技术标签:
【中文标题】为啥程序流控制随机执行【英文标题】:Why program flow control executes randomly为什么程序流控制随机执行 【发布时间】:2017-08-23 21:46:11 【问题描述】:我正在尝试通过编写一个简单的数学学习程序来同时学习数学和 Haskell。
开头是:
-
生成随机数。
过滤这些数字以创建一个易于处理的问题。
显示问题然后接受我的回答
最后,它会将我的答案和正确答案交给另一个函数来给我反馈(“恭喜”--或--“抱歉,正确答案为空白)。
由于某种原因,祝贺功能结束后,它似乎随机选择了下一步,要么:
-
它返回到 main(这是我期望它做的)。
或者在随机循环中,它会立即进入数学测试功能。发生这种情况时,上面的 步骤 2 不会发生,我开始在问题中得到小数。然后它可能会重复此步骤或返回 main。
在尝试调试问题时,我会一直按 RETURN,它会在不同的时间发生。我还添加了一些调试“打印”语句。
这是程序中的 3 个函数。注意 main 调用 funPercentOfNumberToAnother:
funPercentOfNumberToAnother :: IO ()
funPercentOfNumberToAnother = do
(percentDec, percentStr) <- getPercent
ofNum <- getDecimal (200 :: Decimal)
let isNum = percentDec * ofNum
if uglyAnswers ([ofNum, isNum], [percentDec])
then do
putStrLn ("ofNum: " ++ show ofNum)
putStrLn ("isNum: " ++ show isNum)
putStrLn "___________________________"
funPercentOfNumberToAnother
else do
putStrLn ("ofNum: " ++ show ofNum)
putStrLn ("isNum: " ++ show isNum)
putStrLn "Percents"
-- putStrLn "\n\n"
putStrLn (show isNum ++ " is what percent of " ++ show ofNum ++ "?\n" )
putStr "> "
ans <- getLine
submitStringAnswer (ans, percentStr ++ "%")
submitStringAnswer :: (String, String) -> IO ()
submitStringAnswer (myAns, correctAns) = do
if myAns == correctAns
then putStrLn "Congratz!"
else do
putStrLn ("Sorry the correct answer is: " ++ show correctAns)
pause
pause :: IO ()
pause = do
x <- getLine
putStrLn ""
这是我的调试输出。请注意,它提供小数的唯一时间是在 pause 结束后它没有立即返回 main 之后。
__ __ _ _ _ _
| \/ | __ _| |_| |__ ___ _ __ ___ __ _| |_(_) ___ ___
| |\/| |/ _` | __| '_ \ / _ \ '_ ` _ \ / _` | __| |/ __/ __|
| | | | (_| | |_| | | | __/ | | | | | (_| | |_| | (__\__
|_| |_|\__,_|\__|_| |_|\___|_| |_| |_|\__,_|\__|_|\___|___/
1.) Learn Math
2.) Math Lookup
3.) Quit Excolo
1
ofNum: 35
isNum: 15.75
___________________________
ofNum: 120
isNum: 102
Percents
102 is what percent of 120?
>
Sorry the correct answer is: "85%"
15.75 is what percent of 35?
>
Sorry the correct answer is: "45%"
__ __ _ _ _ _
| \/ | __ _| |_| |__ ___ _ __ ___ __ _| |_(_) ___ ___
| |\/| |/ _` | __| '_ \ / _ \ '_ ` _ \ / _` | __| |/ __/ __|
| | | | (_| | |_| | | | __/ | | | | | (_| | |_| | (__\__
|_| |_|\__,_|\__|_| |_|\___|_| |_| |_|\__,_|\__|_|\___|___/
1.) Learn Math
2.) Math Lookup
3.) Quit Excolo
1
ofNum: 80
isNum: 44
Percents
44 is what percent of 80?
>
Sorry the correct answer is: "55%"
__ __ _ _ _ _
| \/ | __ _| |_| |__ ___ _ __ ___ __ _| |_(_) ___ ___
| |\/| |/ _` | __| '_ \ / _ \ '_ ` _ \ / _` | __| |/ __/ __|
| | | | (_| | |_| | | | __/ | | | | | (_| | |_| | (__\__
|_| |_|\__,_|\__|_| |_|\___|_| |_| |_|\__,_|\__|_|\___|___/
1.) Learn Math
2.) Math Lookup
3.) Quit Excolo
1
ofNum: 15
isNum: 2.25
___________________________
ofNum: 60
isNum: 0.6
___________________________
ofNum: 40
isNum: 30
Percents
30 is what percent of 40?
>
Sorry the correct answer is: "75%"
0.6 is what percent of 60?
>
Sorry the correct answer is: "1%"
2.25 is what percent of 15?
>
Sorry the correct answer is: "15%"
如果有帮助,到目前为止我发现的唯一与远程相关的是:Second of several forked processes does not run in Haskell 。
最后,如果这有助于您制定答案,我就处于 Monads 的入门级。
如果任何人都可以提供任何帮助,我将不胜感激,了解发生了什么,id est,为什么它在 pause 结束后没有直接返回到 main,以及为什么它会跳过小数过滤器。
谢谢^^
【问题讨论】:
【参考方案1】:在funPercentOfNumberToAnother
,你有这个子句:
if uglyAnswers ([ofNum, isNum], [percentDec])
then do
putStrLn ("ofNum: " ++ show ofNum)
putStrLn ("isNum: " ++ show isNum)
putStrLn "___________________________"
funPercentOfNumberToAnother
else do
putStrLn ("ofNum: " ++ show ofNum)
putStrLn ("isNum: " ++ show isNum)
putStrLn "Percents"
如果数字很难看,您的意图是回到函数的开头并重新开始;或者继续向用户显示数字。尽其所能,但问问你自己......这个if
子句的末尾会发生什么?在 then
或 else
执行完毕后,无论如何都会执行不在 then
或 else
分支中的内容。
所以,当你得到一些丑陋的数字时,你会开始一个递归调用,寻找更好的数字并显示它们。然后当递归调用完成时,你继续向用户显示原始的、丑陋的数字!
您将需要一个不同的控制流程,例如编写一个始终返回一个不难看的数字的函数,然后在您的(现在是非递归的)funPercentOfNumberToAnother
函数中使用它。或者您可以将函数主体的其余部分(向用户显示数字的部分)拉入 if
的 else
部分,这样您就不会为丑陋的数字这样做。
【讨论】:
【参考方案2】:根据 amalloy 的精彩解释,我了解发生了什么并修复了问题,然后测试了该问题。在 if 语句之外有代码:
if uglyAnswers
then funPercentOfNumberToAnother
else ...
当递归停止时,导致错误的答案后来下降。所以基本上我是在囤积它们。
也许这可以更好地解释它。看到我在第一次尝试时得到了一个干净的答案,所以它不必经过递归。第二次调用有两个电话,因为第一次电话找到了分数答案:
__ __ _ _ _ _
| \/ | __ _| |_| |__ ___ _ __ ___ __ _| |_(_) ___ ___
| |\/| |/ _` | __| '_ \ / _ \ '_ ` _ \ / _` | __| |/ __/ __|
| | | | (_| | |_| | | | __/ | | | | | (_| | |_| | (__\__
|_| |_|\__,_|\__|_| |_|\___|_| |_| |_|\__,_|\__|_|\___|___/
1.) Learn Math
2.) Math Lookup
3.) Quit Excolo
1
In the else statement
===================================
Finally outside the else statement
ofNum: 10
isNum: 4
__ __ _ _ _ _
| \/ | __ _| |_| |__ ___ _ __ ___ __ _| |_(_) ___ ___
| |\/| |/ _` | __| '_ \ / _ \ '_ ` _ \ / _` | __| |/ __/ __|
| | | | (_| | |_| | | | __/ | | | | | (_| | |_| | (__\__
|_| |_|\__,_|\__|_| |_|\___|_| |_| |_|\__,_|\__|_|\___|___/
1.) Learn Math
2.) Math Lookup
3.) Quit Excolo
1
Bad answer alert!
===================================
In the else statement
===================================
Finally outside the else statement
ofNum: 160
isNum: 80
===================================
Finally outside the else statement
ofNum: 55
isNum: 0.55
这是来自原始问题的可行代码sn-ps:
funPercentOfNumberToAnother :: IO ()
funPercentOfNumberToAnother = do
(percentDec, percentStr) <- getPercent
ofNum <- getDecimal (200 :: Decimal)
let isNum = percentDec * ofNum
if uglyAnswers ([ofNum, isNum], [percentDec])
then funPercentOfNumberToAnother
else do
let message = show isNum ++ " is what percent of " ++ show ofNum ++ "?\n"
testProblem (percentStr ++ "%", message)
testProblem :: (String, String) -> IO ()
testProblem (correctAns, message) = do
putStrLn message
putStrLn "\n\n"
putStr "> "
myAns <- getLine
if myAns == correctAns
then putStrLn "Congratz!"
else do
putStrLn ("Sorry the correct answer is: " ++ show correctAns)
pause
【讨论】:
以上是关于为啥程序流控制随机执行的主要内容,如果未能解决你的问题,请参考以下文章