【问题标题】:Trouble with combined logic in rubyruby 中组合逻辑的问题
【发布时间】:2010-11-30 20:50:37
【问题描述】:

编写中子束的简单蒙特卡罗模拟。几何逻辑有问题(无论是在一种环境还是另一种环境中)。我的问题是 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 个浮点数调用它,在逻辑中设置几何图形,然后你会明白我的意思。

我的问题是:如何在没有一大堆嵌套 if 的情况下让它按应有的方式工作(即正确评估逻辑)? (这就是我即将重制的内容,但是阅读起来是一场噩梦,而且内存很便宜。)

【问题讨论】:

  • 您能否更具体地说明您希望它如何评估逻辑?代码应该输出什么?
  • 好吧,目前我只想看看赋予各个域的真值。这取决于参数数组。我的问题在第一组 puts 语句中概述,评估逻辑的顺序很重要,当它不应该 不管我是否使用 &&,|| or or and and and,这是为什么呢?我不认为是这样,但是:我正在使用 jEdit 解释器(我确信它只是在我的 PATH 中查找)。

标签: ruby logic


【解决方案1】:

您曾多次输入“Sheild”,而您的意思可能是“Shield”

在您使用它们的上下文中,您应该使用&amp;&amp; 而不是and|| 而不是or,以及! 而不是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

一旦您将所有这些谓词作为自己的方法,您就可以创建一个方法来确定材料,如下所示:

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

沿着这条线继续,直到只剩下一袋小而专注的方法。

【讨论】:

  • 谢谢你!一切都是对象是一个奇怪的概念。
  • 我已经围绕这个系统进行了构建,它运行良好,感谢您的建议!以后处理复杂逻辑的时候肯定会用到这个。
【解决方案2】:

将所有andor 更改为&amp;&amp;||

以前从未见过有人真正使用array.at(index) 而不是array[index]

我还建议不要使用*args,而是支持将哈希参数作为一种命名参数

def test(params)
  x = params[:x] || raise("You have to provide x!")
  y = params[:y] || raise("You have to provide y!")
  z = params[:z] || raise("You have to provide z!")
  puts x, y, z
end

并使用(Ruby 1.9+ 语法)调用它

test({x: 42, y: 4711, z: 93})

42
4711
93

【讨论】:

  • 如果您使用fetch,如果密钥不存在,则不需要raise
  • @Andrew 是的,但 IndexError: key not found 信息量不是很大。
  • 这是 ruby​​ 吸引我的特性之一。我忘记了哈希参数,谢谢,现在就去玩。
  • @morb 它应该有,因为它们是相同的。 “array.at(index) ... 另见 Array#[]。” - ruby-doc.org/ruby-1.9/classes/Array.html#M000696
  • 是的,这是我一直用来学习的网站之一。我对编程没有特别深入的了解,所以当我看到有两种方法可以从数组中访问信息时,我只是假设有更深层次的原因,当我得到输出时很高兴。
【解决方案3】:

尝试使用&amp;&amp; 代替and|| 代替or! 代替not

您的问题可能是优先问题 - 阅读 this article 了解更多信息。

【讨论】:

  • 或者只是对括号的使用非常虔诚。
  • 它可以帮助我更好地阅读,并且我已经完成了运算符的所有排列。我今天才发现你可以使用 and and or, I am a Ruby noob.
  • 我确实测试过 && 和 ||,它们的优先级似乎无关紧要。
【解决方案4】:

查看您的代码,您设置它的方式是将四个“材料”变量设置为布尔值。然后将这些布尔值输入 if-elsif-else 块。

这样做的问题是,第一个返回 true 的 if 将退出 if-elsif-else 块。如果这就是您保持第一个值的意思,那么这是一个非常可预测的结果。

【讨论】:

  • philosodad:谢谢,还有很多东西要学。我以为是这样的。
  • 哦,实际上没有。这是程序逻辑的一部分,它从一个中心点向外工作,测试位置(以 arg 形式给出的数组)是否在特定域中,并且如果 else 则 supposed 退出在第一个真值上。
猜你喜欢
  • 2011-05-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-11-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多