我要求 Netlogo 创建代表旧车、中年车和新车的海龟作为代理,每个都有一定的固定百分比(分别为 65%、30% 和 5%)。我在用户界面中有一个滑块,用于设置汽车总数,代码会计算这些比例。所发生的情况是,并不是每次我在设置中都得到准确数量的代理。例如,对于在 UI 中设置的 10 个代理,我总共设置了 9 辆车,其中 6 辆是旧车,3 辆是中年车,0 辆是新车。我想我希望代码对这些数字进行四舍五入,以使设置的代理总数与 UI 中显示的代理总数相匹配。 我的代码如下:
to create-ICE-engine-cars
let ICE-old (cars-ICE-engine * 0.65)
let ICE-middle (cars-ICE-engine * 0.3)
let ICE-new (cars-ICE-engine * 0.05)
ask n-of ICE-old patches with [p-road-data > 9]
[sprout 1]
ask n-of ICE-middle patches with [p-road-data > 9]
[sprout 1]
ask n-of ICE-new patches with [p-road-data > 9]
[sprout 1]
end
我认为对于给定类别而言,向上或向下舍入并不重要。我只需要拥有与 UI 中定义的设置代理数量相同的设置代理。谢谢你。
当您尝试将浮点数用于“sprout”等过程时,Netlogo 会将浮点数舍入到下一个整数。因此,您必须编写一些代码来确保您仍然添加一些额外的汽车。一种方法是首先创建您想要的汽车数量,然后再更改它们。
您可以采取的另一种方法是计算每个类别有多少辆汽车,然后根据随机加权选择分配最后一辆汽车
to test
let cars-ICE-engine 10
let ICE-old (cars-ICE-engine * 0.65)
let ICE-middle (cars-ICE-engine * 0.3)
let ICE-new (cars-ICE-engine * 0.05)
let int-old floor ICE-old
let int-middle floor ICE-middle
let int-new floor ICE-new
let remainder-old ICE-old - int-old
let remainder-middle ICE-middle - int-middle
let remainder-new ICE-new - int-new
let number random-float 1
(ifelse
number <= remainder-old [set int-old int-old + 1]
number <= remainder-old + remainder-middle [set int-middle int-middle + 1]
number <= remainder-old + remainder-middle + remainder-new [set int-new int-new + 1]
)
print int-old
print int-middle
print int-new
end
这种方法不能很好地扩展,因为如果您有更多类别怎么办?如果分配的方式恰好是您缺少超过 1 辆车怎么办? 以下代码通过使用列表和循环可以更好地扩展,但根据您编写程序的目的,它可能有点过头了。
to go-2
let cars-ICE-engine 111034
;Initiate multiple categories
let ICE-old (cars-ICE-engine * 0.35)
let ICE-middle (cars-ICE-engine * 0.3)
let ICE-new (cars-ICE-engine * 0.05)
let ICE-1 (cars-ICE-engine * 0.07)
let ICE-2 (cars-ICE-engine * 0.10)
let ICE-3 (cars-ICE-engine * 0.13)
let ICE-list (list ICE-old ICE-middle ICE-new ICE-1 ICE-2 ICE-3) ;join all the categories into one lit
let int-list map floor ICE-list ;Round all the numbers downfor the actual number of cars each category will get
let remainder-list (map [[a b] -> a - b] ICE-list int-list) ;Calculate the remainder for each number that you rounded down
let to-distribute round sum remainder-list ;Calculate how many cars still need to be distributed
repeat to-distribute [
let number random-float to-distribute
let flag False
let cum-rem-list map [i -> sum sublist remainder-list 0 (i + 1)] range length remainder-list ;I create a new list where each value is the sum of itself and all prior values i nthe remainder-list This list is useful for selecting a category using a random weighted method
foreach range length cum-rem-list [ i ->
if not flag [
if number <= item i cum-rem-list [
set int-list replace-item i int-list (item i int-list + 1) ;I increase the value of the selected category by 1
set to-distribute to-distribute - item i remainder-list ;Subtract the selected value from t-distribute so that the newto-distribute is still the sum of everything in the remainder-list
set remainder-list replace-item i remainder-list 0 ;I remove the selected value from the remainder-list so that it can't be selected again
set flag True
]
]
]
]
print int-list
print sum int-list
end