ruby - ruby 中的组合逻辑问题

标签 ruby logic

编写中子束的简单蒙特卡洛模拟。几何逻辑有问题(无论某物在一个环境还是另一个环境中)。我的问题是 Ruby 似乎按顺序处理条件并保留它到达的第一个值。

下面的代码很好地说明了这一点:

def checkPosition(*args)

  polyCylRad = 2.5
  polyCylFr = 15
  polyCylB = -2.0
  borPolyBoxL = 9.0 / 2
  pbCylRad = 3.0
  pbBoxL = 10.0 / 2
  cdBoxL = 9.5 / 2

  position = Array.new
  material = String.new

  args.each do |item|
    position << item.inspect.to_f
  end
  xSquared = position.at(0) ** 2
  ySquared = position.at(1) ** 2
  zSquared = position.at(2) ** 2
  modX = Math.sqrt(xSquared)
  modY = Math.sqrt(ySquared)
  modZ = Math.sqrt(zSquared)

  puts xSquared
  puts Math.sqrt(ySquared + zSquared) <= polyCylRad
  puts (position.at(0) >= polyCylB)
  puts (position.at(0) <= polyCylFr)
  puts (position.at(0) >= polyCylB)and(position.at(0) <= polyCylFr)
  puts (position.at(0) <= polyCylFr)and(position.at(0) >= polyCylB)

  puts zSquared


  polyCylinder = (Math.sqrt(ySquared + zSquared) <= polyCylRad)and((position.at(0) >= polyCylB)and(position.at(0) <= polyCylFr) )
  puts polyCylinder
  borPolyBox = ((modX <= borPolyBoxL)or(modY < borPolyBoxL)or(modZ <= borPolyBoxL)) and not((modX >= cdBoxL)or(modY >= cdBoxL)or(modZ >= cdBoxL)) and not(Math.sqrt(ySquared + zSquared) <= polyCylRad)
  puts borPolyBox
  cadmiumShield = ((modX <= cdBoxL)or(modY < cdBoxL)or(modZ <= cdBoxL)) and not((modX >= pbBoxL)or(modY >= pbBoxL)or(modZ >= pbBoxL)) and not(Math.sqrt(ySquared + zSquared) <= polyCylRad)
  puts cadmiumShield
  leadShield = ( ((modX <= pbBoxL)or(modY <= pbBoxL)or(modZ <= pbBoxL)) or ((position.at(0) <= ployCylFr)and(Math.sqrt(ySquared + zSquared) <= pbCylRad)) ) and not(Math.sqrt(ySquared + zSquared) <= polyCylRad)
  puts leadShield

  if (polyCylinder) : material = "poly"
  elsif(borPolyBox) : material = "borPoly"
  elsif(cadmiumSheild) : material = "cd"
  elsif(leadSheild) : material = "pb"
  elsif(material == nil) : position = Array.new
  end

  thisEnvironment = Array.new
  thisEnvironment << position << material
  puts thisEnvironment.at(0)
  puts thisEnvironment.at(1)
end

checkPosition(40, 0, 0)

随心所欲地调用代码,但给它 *args 作为参数(我很懒,以后可能想添加更多的 args)然后用 3 个 float 调用它,wrt 逻辑中设置的几何图形和你会明白我的意思。

我的问题是:如何在没有一大堆嵌套 if 的情况下使其正常工作(即正确评估逻辑)? (这就是我要重制的内容,但它是一场噩梦,而且内存很便宜。)

最佳答案

您输入了几次“Sheild”,您可能指的是“Shield”

在你使用它们的上下文中,你应该使用 && 而不是 and|| 而不是 或者! 而不是 not。原因是 orand 的优先级太低,它们会导致您的赋值运算符无法按您希望的方式工作。例如,

a = b and c

评估为

(a = b) and c

这样 a 总是被赋予值 b,然后在结果为真时,c 被评估(并丢弃)。另一方面,

a = b && c

评估为

a = (b && c)

您在此代码中想要的是什么。

除此之外,我会将所有这些代码移到一个类中,这样我就可以为事物创建很多小方法:

class PositionChecker

  def initialize(*args)
    @x, @y, @z = *args
  end

  def checkPosition
    ...
  end

end

寻找机会用方法调用替换 checkPosition 中的局部变量。例如,您可以将 borPolyBox 移动到它自己的方法中(一旦它使用的所有值都是它们自己的方法):

class PositionChecker
  ...
  def borPolyBox
    ((modX <= borPolyBoxL)||(modY < borPolyBoxL)||(modZ <= borPolyBoxL)) && !((modX >= cdBoxL)||(modY >= cdBoxL)||(modZ >= cdBoxL)) && !(Math.sqrt(ySquared + zSquared) <= polyCylRad)
  end
  ...
end

将所有这些谓词作为它们自己的方法后,您可以创建一个方法来确定 Material ,如下所示:

def material
  [
    [:polyCylinder, 'poly'],
    [:borPolyBox, 'borPoly'],
    [:cadmiumShield, 'cd'],
    [:leadShield, 'pb'],
  ].each do |method, name|
    return name if send(method)
  end
  nil
end

还有一个职位:

def position
  [@x, @y, @z] if material
end

沿着这条线继续,直到只剩下一袋极小的、集中的方法。

关于ruby - ruby 中的组合逻辑问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4318481/

相关文章:

ruby-on-rails - 在 Ruby 中使用 Map 和 Select 方法一起遍历数组

ruby - 使用主管运行 'bundle exec middleman server'

ruby-on-rails - 在 rails 的 html.erb 模板中阻止评论

ruby-on-rails - Ruby语法 “OR”运算符

ruby - JSON的基于流的解析和写入

mysql - 在我的数据库表中查找重复项的最佳方法是什么

python - "do this in one pass"是什么意思?

c# - 从可用纸张尺寸列表中获取最接近的纸张尺寸

java - 如何创建 Battleship 战舰游戏算法

java - Java ATM 项目中使用 If 语句进行切换