3

我正在尝试编写一个使用随机数在循环中更改 3 个坐标和 3 个速度的函数。尽管他生成的数字似乎足够随机。最后两个值永远不会分开,而第一个值确实走自己的路。

这是功能,我还将链接 excel 工作簿,因此您可以看到它的实际效果(它是一个使用 RGB 和滑块作为值的动画颜色框。只需运行“颜色”子

Function variate(ByRef x_origin As Double, ByRef y_origin As Double, ByRef offset_x As Double, ByRef offset_y As Double, Optional ByRef z_origin As Double, Optional ByRef offset_z As Double, Optional xyz_bounds) As Variant
'this function adds random number to each of the origins
'the offset is the 'drift' the object has (or velocity)
'calculate a random number
'if the number is going in the same direction, speed up
'otherwise slow down
Dim new_origin_x As Double
Dim new_origin_y As Double
Dim new_origin_z As Double
Dim velocity_x As Double
Dim velocity_y As Double
Dim velocity_z As Double
Dim speed_x As Double
Dim speed_y As Double
Dim speed_z As Double
Dim random_number_x As Double
Dim random_number_y As Double
Dim random_number_z As Double
Dim random_speed_x As Double
Dim random_speed_y As Double
Dim random_speed_z As Double
'calculate a random with the seed and make it between -0.5 and 0.5
    Randomize
    random_number_x = Rnd(Range("x_fact").Value) - 0.5
    Randomize
    random_number_y = Rnd(Range("y_fact").Value) - 0.5
    Randomize
    random_number_z = Rnd(Range("z_fact").Value) - 0.5
    'for the speed
    Randomize
    random_speed_x = Rnd(1) - 0.5
    Randomize
    random_speed_y = Rnd(1) - 0.5
    Randomize
    random_speed_z = Rnd(1) - 0.5
'see how much there is a speed up
'what point would we be at with the current speed
'that is the distance travelled in time, but the time is 1 'unit' ...
'and let's add some randohohomnessss
    speed_x = offset_x + (random_speed_x / Range("x_rem").Value)
    speed_y = offset_y + (random_speed_y / Range("y_rem").Value)
    speed_z = offset_z + (random_speed_z / Range("z_rem").Value)
 'so new origin is new_origin_x = x_origin + offset_x
 'but than we've travelled at the same speed, with directional changes
 'we're probably not even moving
 'so add some randomness to act as 'live'
    new_origin_x = x_origin + offset_x + (random_number_x / Range("x_fact").Value)
    new_origin_y = y_origin + offset_y + (random_number_y / Range("y_fact").Value)
    new_origin_z = y_origin + offset_z + (random_number_z / Range("z_fact").Value)
'variate = [{new_origin_x;new_origin_y};{speed_x;speed_y}]
'variate = [{new_origin_x;new_origin_z};{speed_x;speed_z}]
'see if boundaries are requested and if so, not met
'should be: going to meet at the current speed
 If Not IsMissing(xyz_bounds) Then
   Dim distant_from_bounds_x
   Dim distant_from_bounds_y
   Dim distant_from_bounds_z
   Dim future_pos_x
   Dim previous_dist_x
   Dim previous_dist_y
   Dim previous_dist_z
   future_pos_x = new_origin_x + 3 * speed_x
   Dim future_pos_y
   future_pos_y = new_origin_y + 3 * speed_y
   Dim future_pos_z
   future_pos_z = new_origin_z + 3 * speed_z
   distant_from_bounds_x = xyz_bounds / 2 - Abs(future_pos_x - xyz_bounds / 2)
   distant_from_bounds_y = xyz_bounds / 2 - Abs(future_pos_y - xyz_bounds / 2)
   distant_from_bounds_z = xyz_bounds / 2 - Abs(future_pos_z - xyz_bounds / 2)
   previous_dist_x = xyz_bounds / 2 - Abs((x_origin + 3 * speed_x) - xyz_bounds / 2)
   previous_dist_y = xyz_bounds / 2 - Abs((y_origin + 3 * speed_y) - xyz_bounds / 2)
   previous_dist_z = xyz_bounds / 2 - Abs((z_origin + 3 * speed_z) - xyz_bounds / 2)
   'slow down
   If (distant_from_bounds_x < 10) And (distant_from_bounds_x - previous_dist_x < 0) Then
        speed_x = speed_x - speed_x / 3
        If Abs(speed_x) < 1.5 Then speed_x = -speed_x * 2.9
   End If
   If distant_from_bounds_y < 10 And (distant_from_bounds_y - previous_dist_y < 0) Then
        speed_y = speed_y - speed_y / 3
        If Abs(speed_y) < 1.5 Then speed_y = -speed_y * 2.9
   End If
   If distant_from_bounds_z < 10 And (distant_from_bounds_z - previous_dist_z < 0) Then
        speed_z = speed_z - speed_z / 3
       If Abs(speed_z) < 1.5 Then speed_z = -speed_z * 2.9
    End If
    'speedlimits
    If Abs(speed_x) > 9 Then speed_x = speed_x - Abs(speed_x / 4)
    If Abs(speed_y) > 9 Then speed_y = speed_y - Abs(speed_y / 4)
    If Abs(speed_z) > 9 Then speed_z = speed_z - Abs(speed_z / 4)
 End If
'return the values and the new velocity to add some more stuff

x_origin = new_origin_x
y_origin = new_origin_y
z_origin = new_origin_z
offset_x = speed_x
offset_y = speed_y
offset_z = speed_z

End Function

任何建议将不胜感激 !

4

1 回答 1

7

如果你能原谅我的粗鲁,那你就是在滥用生成器:

1)在函数的开头,包括该行

  Rnd(-1)

这就是您为生成器播种的方式。

2) 删除所有Randomize调用,因为它们破坏了生成器的统计属性。我认为这是你的问题的原因。您可以在上述Randomize之后直接打一个电话Rnd(-1),但我认为生成相同的序列以提高可处理性是件好事。

3) 调用中不需要有参数Rnd()(除了第一步),因为默认行为是返回范围 [0, 1) 内的数字。事实上,这可能会导致您的问题,因为负参数值会重新播种生成器!

4) 调查执行上述操作的效果。但请注意,VBA 随机序列是一个线性同余生成器next = ((c * prev) mod b) + a其中a和是常数,b是前一个随机数和生成的随机数。(作为最后的繁荣,整数值被缩放为浮点数)。您可以看到序列中可能存在自相关,因为当很小时,模数将不起作用。您可以但希望 Microsoft 的工程师已经分配了很大的价值来规避这种影响。在多维情况下使用随机数时,这种自相关可能会导致“粘连”。cprevnextnextprevprevc

(4) 因此可能会导致您的问题,如果是,您需要切换到另一台发电机。让我知道,我们可以在这方面提出一些建议。

于 2013-06-19T12:09:03.200 回答