ie-developers / ie-questions

public questions for ie students.
10 stars 0 forks source link

readProcessの結果が同じになってしまう #17

Closed maeken2010 closed 9 years ago

maeken2010 commented 9 years ago

ex_bp_oというCで書かれたプログラムの実行結果をhaskellで解析しようと思ってます.ex_bp_oは某先生のBP学習を行うプログラムで,実行する度に実行結果が変わります.readProcessを用いて複数回実行したいのですが,どれも実行結果が同じになってしまいます.例えば以下の様なコードを実行すると,aとbは全く同じ結果が帰ってきます.

import System.Process

main = do
   a <- (take 2.reverse.lines) <$> runExBpO
   b <- (take 2.reverse.lines) <$> runExBpO
   print a
   print b

runExBpO = do
    s <- readProcess "./ex_bp_o" [] []
    return s

これもhaskellの透過参照性な性質のせいでしょうか.

atton commented 9 years ago

readProcess は IO String なので、実行する度に結果は変わると思います。 実際 uuidgen コマンドを二度実行すると結果が2種類出てきます。

import System.Process

main = do
   a <- (take 2.reverse.lines) <$> runExBpO
   b <- (take 2.reverse.lines) <$> runExBpO
   print a
   print b

runExBpO = do
    s <- readProcess "uuidgen" [] []
    return s
$ ghc hoge.hs
$ ./hoge
["C64E2A3D-0FD9-48BA-83E3-0940ECE97D70"]
["CFA0F259-8B78-4C61-8DEF-50373835E83B"]

ちなみに ./ex_bp_o はコマンドラインで二度実行しても別の結果になりますか?

atton commented 9 years ago

ex_bp_o が手元にあったので実行してみましたが、手で実行する分には違う結果になりますね。

ソースを見ると、乱数の seed の取り方が

    srand((int)time((long *)0));

になってるので、同じ秒内に実行されてしまうと同じ seed になって同じ結果になるみたいです。

例えば hoge.c として

#include<time.h>
#include<stdio.h>

int main(int argc, char const* argv[]) {
    printf("%d", (int)time((long *)0));
    return 0;
}

を作って同じように2回 readProcess すると

$ ./hoge
["1432295110"]
["1432295110"]

と同じ値が出るのでこれが原因ですね。 seed の生成方法を変えるか、n秒sleepするなりすると違う結果が得られると思います。

maeken2010 commented 9 years ago

ex_bp_oの問題だったのですね… 無事に異なる結果を得られるようになりました!ありがとうございました