lib/games_dice/probabilities.rb in games_dice-0.3.3 vs lib/games_dice/probabilities.rb in games_dice-0.3.5
- old
+ new
@@ -24,11 +24,11 @@
# @param [Array<Float>] probs Each entry in the array is the probability of getting a result
# @param [Integer] offset The result associated with index of 0 in the array
# @return [GamesDice::Probabilities]
def initialize( probs = [1.0], offset = 0 )
# This should *probably* be validated in future, but that would impact performance
- @probs = probs
+ @probs = check_probs_array probs.clone
@offset = offset
end
# @!visibility private
# the Array, Offset representation of probabilities.
@@ -216,10 +216,17 @@
end
end
GamesDice::Probabilities.new( new_probs, combined_min )
end
+ # Returns a symbol for the language name that this class is implemented in. The C version of the
+ # code is noticeably faster when dealing with larger numbers of possible results.
+ # @return [Symbol] Either :c or :ruby
+ def self.implemented_in
+ :ruby
+ end
+
# Adds a distribution to itself repeatedly, to simulate a number of dice
# results being summed.
# @param [Integer] n Number of repetitions, must be at least 1
# @return [GamesDice::Probabilities] new distribution
def repeat_sum n
@@ -283,9 +290,23 @@
end
GamesDice::Probabilities.new( new_probs, new_offset )
end
private
+
+ def check_probs_array probs_array
+ probs_array.map!{ |n| Float(n) }
+ total = probs_array.inject(0.0) do |t,x|
+ if x < 0.0 || x > 1.0
+ raise ArgumentError, "Found probability value #{x} which is not in range 0.0..1.0"
+ end
+ t+x
+ end
+ if (total-1.0).abs > 1e-6
+ raise ArgumentError, "Total probabilities too far from 1.0 for a valid distribution"
+ end
+ probs_array
+ end
def calc_keep_distributions k, q, kmode
if kmode == :keep_best
keep_distributions = [ GamesDice::Probabilities.new( [1.0], q * k ) ]
if p_gt(q) > 0.0 && k > 1