如何在单位圆上生成随机三角形

时间:2014-04-10 13:30:36

标签: haskell

我试图找出单位圆的中心落入三角形的概率。在单位圆上随机选取三角形的顶点。

我的想法是在x范围内选择随机浮点(-1.0, 1.0),然后随机选择向上或向下。这将给我一点(x, +/-sqrt(1 - x*x))

import Data.Random

main = do
 x <- randomRIO (-1.0,1.0)
 let y =  (sample (randomElement [-1,1])) * sqrt(1-x*x))   -- I can't make this line work

那么如何从[Int]中选择一个随机元素?

3 个答案:

答案 0 :(得分:5)

我不会说Haskell,但是要选择具有均匀分布的圆上的点,您需要选择的变量就是角度。

angle <- randomRIO(-pi, pi)

然后

y = sin(angle)
x = cos(angle)

为3个点选择3个角度,这会给你一个随机的三角形。

至于测试中心是否在三角形中,我相当肯定,虽然到目前为止我还没有演示,你可以如下:

  • 找到最长的边缘。边缘将圆圈分成两部分
  • 如果第三个顶点位于最小部分,则中心不在三角形
  • 否则,它是

编辑,演示

  • 设ABC,ABC为中心D圆的三角形。
  • 让AB成为最长边
  • 设C位于由AB
  • 切割的圆的最大一半上
  • 如果D不在ABC中,那么AC或BC(为简单起见,因为这只是命名约定,假设AC)是AB和D之间三角形的边缘
  • AC和AB是圆的和弦,最靠近中心的是最长的
  • AC长于AB

如何仅将此应用于角度

从前面的演示中可以看出,如果所有3个点都在同一半,则中心不在三角形中,否则就是。

因此,要点是确定2点之间的最大距离为pi。

感谢J. Abrahamson,我们可以计算所有三个点之间的差异,并将较小的两个相加,如果总和大于pi,则返回true。

2点之间距离的实际测量是这样的,因为我们需要2之间的绝对和最直接的距离:

  • 计算绝对距离diff = abs(theta1 - theta2)
  • 如果这不仅仅是pi,请使用2 * pi - diff

答案 1 :(得分:0)

使用MonadRandom包代替(cabal install MonadRandom)的一个示例:

import Control.Monad.Random

type R a = Rand StdGen a  -- Just a type alias for less typing

type Point = (Double, Double)
type Triangle = (Point, Point, Point)

-- Monadic action
genAngle :: R Double
genAngle = getRandomR (-pi, pi)

-- Monadic action
genPoint :: R Point
genPoint = do
    x <- genAngle
    return (cos x, sin x)

-- Monadic action
genTriangle :: R Triangle
genTriangle = do
    a <- genPoint
    b <- genPoint
    c <- genPoint
    return (a, b, c)

-- Pure function
containsOrigin :: Triangle -> Bool
containsOrigin (a, b, c) = ???  -- You get to implement this (@njzk2 has given some pointers)

-- Monadic action
genTriangles :: R [Triangle]
genTriangles = do
    tri <- genTriangle
    rest <- genTriangles -- Recursion to get infinite list
    return $ tri : rest
-- Monadic action
genTrianglesWithOrigin :: R [Triangle]
genTrianglesWithOrigin = do
    triangles <- genTriangles
    return $ filter containsOrigin triangles

main :: IO ()
main = do
    triangles <- fmap (take 10) $ evalRandIO genTrianglesWithOrigin
    mapM_ print triangles

如果您想更多地了解为什么MonadRandom比基本random包更好,我建议您查看Learn You A Haskell的this部分。基本上,MonadRandom构建了一个更好的界面,其中并非所有内容都在IO中(这很危险,谁知道IO函数的作用)并提供了一些简单的函数来生成随机数,而random包只提供了最准确的准系统功能。事实上,Rand monad只不过是伪装的State monad,它只是跟上你的生成器种子的状态。

答案 2 :(得分:0)

查看MonadRandom包,统一函数将从值列表中给出一个随机值(在您的情况下为[Int])。我在手机上,但找到包裹不应该太难。如果你想使用不同的发行版,请查看random-fu。