ofRandom(min, max)はmaxを返すか問題

ofRandomっていつも最大値含むか忘れるんだよなー.
と思った事から始まったこの問題.

ぱっとソース眺めて

rand() / (RAND_MAX + 1.0f)


なるほど. そうかそうか, 含まないな.

と思ったのだけどなんか不安になって確認したら
RAND_MAX / (RAND_MAX + 1.0f) == 1.0f
がtrueだと?

ということで@torutoruと色々floatの表現とか調べたりしてて

float f = RAND_MAX + 1.0f, g = RAND_MAX;
if(f == g) printf("Fuck!!");

Fuck!!

oh…

ということで32bit floatだと精度落ちするんですね.
なんで static_cast<float>(RAND_MAX) じゃないのかが分からない.

と思ってたら,

@2bbb Visual StudioだとRAND_MAXが0x7fffなので環境依存バグっぽいです。 https://msdn.microsoft.com/ja-jp/library/2dfe3bzd.aspx …
解決むずかしいですね。変に結果をいじると確率変わっちゃいますし。

(http://twitter.com/novogrammer/status/588670294304296961)と.

これは環境依存バグだなーと.

ただ, 正解が分からない. ソースのコメントも minからmaxの範囲の, 的な曖昧なことしか書いてなくて, [min, max] なのか [min, max) なのかがはっきりしない.
のでVisual StudioとXcodeのどっちが狙った結果なのかも分からない.
[min, max] だったら static_cast<float>(RAND_MAX) とかにすれば良いし, [min, max) だったら (RAND_MAX + 1.0) とかにすれば取り敢えず大丈夫な気はする.

とかまあ色々考えてたんだけど,

for(int i = 0; i < RAND_MAX; i++) if(1.0f == i / (RAND_MAX + 1.0f)) c++;


63を返すし, まあ, 問題の領域は 63/2^31 で大体 0.0000029% の確率と.

そして, やりたいことは

ofColor c;
c.r = ofRandom(256);


的ながやりたいだけなので, どうせオーバーフロー起こして大体問題無いんですよねー. ってことに気付きました.まあ,

c.r = ofRandom(255.999f);


くらいにしとくのが妥当なのかなー.

ということで頑張ってissue立てました. 英語通じるかなー…

結論: 英語難しい.


追記:

https://github.com/openframeworks/openFrameworks/issues/3762#issuecomment-93818052

最新のレポジトリの`ofMath.h`には
A random number in the range [0, max) will be returned.
って書いてあることに気付きました. まさにその情報が欲しかったの…
ちゃんと見なきゃですね…

ただ, それでも

rand() / (RAND_MAX + 1.0f);


が環境によっては1.0fを取り得るということは変わらないので修正してPR投げようと思います.
全部同じコードが直書きで使われてるから ofRandomf() にinline付けてそこだけ1.0に修正して他を差し替えたいところ.

コメントを残す