Calculations on the iteration count in for loop - ruby

I was playing around with Ruby and Latex to create a color coding set for a registor. I have the following block of code. When attempting to run this, band1 = 1e+02.
I tried band1 = (BigDecimal(i) * 100).to_f, thinking maybe there was some odd floating point issue. An integer multiplied by an integer should create an integer. I tried a variety of other things as well, but to no avail.
(1..9).each do |i| #Band 1
(0..9).each do |j| #Band 2
(0..11).each do |k| #Band 3
#Band 3 Start
#these are the colors of the resistor bands
b1 = $c_band12[i]
b2 = $c_band12[j]
b3 = $c_band3[k]
b4 = "Gold"
oms = ((i*100) + (j*10)) * $mult[k]
band1 = i*100
band2 = j
band3 = $mult[k]
end
end
end
Not sure what I'm missing. Should I be using each_with_index through these iterations? I tried this:
(1..9).each_with_index {|i, indexi| #Band 1
(0..9).each_with_index {|j, indexj| #Band 2
(0..11).each_with_index {|k, indexk| #Band 3
#Band 3 Start
#these are the colors of the resistor bands
b1 = $c_band12[i]
b2 = $c_band12[j]
b3 = $c_band3[k]
b4 = "Gold"
oms = ((i*100) + (j*10)) * $mult[k]
band1 = indexk * 100
and I got the same answer. I can't see why 1*100 should equate to such a large number.
edit: Additional info: If I have this: band1=i*10
then the calculation is correct. In fact, the calculation is correct up to 99.

In your code, band1 has to be a Fixnum. Check with p band1.class. Not sure how you get "1e+02", maybe you print in some strange fashion, or you do band1 == 1e+02 which returns true in Ruby. You must use eql? to distinguish between 1 and 1.0:
1 == 1.0 # => true
1.eql?(1.0) # => false

Related

Is it possible to do a poisson distribution with the probabilities based on integers?

Working within Solidity and the Ethereum EVM and Decimals don't exist. Is there a way I could mathematically still create a Poisson distribution using integers ? it doesnt have to be perfect, i.e rounding or losing some digits may be acceptable.
Let me preface by stating that what follows is not going to be (directly) helpful to you with etherium/solidity. However, it produces probability tables that you might be able to use for your work.
I ended up intrigued by the question of how accurate you could be in expressing the Poisson probabilities as rationals, so I put together the following script in Ruby to try things out:
def rational_poisson(lmbda)
Hash.new.tap do |h| # create a hash and pass it to this block as 'h'.
# Make all components of the calculations rational to allow
# cancellations to occur wherever possible when dividing
e_to_minus_lambda = Math.exp(-lmbda).to_r
factorial = 1r
lmbda = lmbda.to_r
power = 1r
(0...).each do |x|
unless x == 0
power *= lmbda
factorial *= x
end
value = (e_to_minus_lambda / factorial) * power
# the following double inversion/conversion bounds the result
# by the significant bits in the mantissa of a float
approx = Rational(1, (1 / value).to_f)
h[x] = approx
break if x > lmbda && approx.numerator <= 1
end
end
end
if __FILE__ == $PROGRAM_NAME
lmbda = (ARGV.shift || 2.0).to_f # read in a lambda (defaults to 2.0)
pmf = rational_poisson(lmbda) # create the pmf for a Poisson with that lambda
pmf.each { |key, value| puts "p(#{key}) = #{value} = #{value.to_f}" }
puts "cumulative error = #{1.0 - pmf.values.inject(&:+)}" # does it sum to 1?
end
Things to know as you glance through the code. Appending .to_r to a value or expression converts it to a rational, i.e., a ratio of two integers; values with an r suffix are rational constants; and (0...).each is an open-ended iterator which will loop until the break condition is met.
That little script produces results such as:
localhost:pjs$ ruby poisson_rational.rb 1.0
p(0) = 2251799813685248/6121026514868073 = 0.36787944117144233
p(1) = 2251799813685248/6121026514868073 = 0.36787944117144233
p(2) = 1125899906842624/6121026514868073 = 0.18393972058572117
p(3) = 281474976710656/4590769886151055 = 0.061313240195240384
p(4) = 70368744177664/4590769886151055 = 0.015328310048810096
p(5) = 17592186044416/5738462357688819 = 0.003065662009762019
p(6) = 1099511627776/2151923384133307 = 0.0005109436682936699
p(7) = 274877906944/3765865922233287 = 7.299195261338141e-05
p(8) = 34359738368/3765865922233287 = 9.123994076672677e-06
p(9) = 67108864/66196861914257 = 1.0137771196302974e-06
p(10) = 33554432/330984309571285 = 1.0137771196302975e-07
p(11) = 33554432/3640827405284135 = 9.216155633002704e-09
p(12) = 4194304/5461241107926203 = 7.68012969416892e-10
p(13) = 524288/8874516800380079 = 5.907792072437631e-11
p(14) = 32768/7765202200332569 = 4.2198514803125934e-12
p(15) = 256/909984632851473 = 2.8132343202083955e-13
p(16) = 16/909984632851473 = 1.7582714501302472e-14
p(17) = 1/966858672404690 = 1.0342773236060278e-15
cumulative error = 0.0

Two very close floating point numbers are not equal

In IRB:
0.9999999999999998 == 1.0
# => false
0.99999999999999998 == 1.0
# => true
Also just showing the inspect values:
0.9999999999999998
# => 0.9999999999999998
0.99999999999999998
# => 1.0
In my case the value created by my program is unfortunately the first one, so I'm having trouble writing a test case which validates the value as equal to one.
I am deciding between the following options:
add round calls in the application code, however the application is already working, I just am unable to test
add round calls in the testing code
???
What would be your recommended approach? Is there a way I can configure my program to treat 0 with fifteen nines after the decimal as equal to 1.0? It feels a bit frustrating because sixteen nines after the decimal seems to be the cut off - I'm only one short.
Reading this article on how to compare small floating-point differences:
http://c-faq.com/fp/fpequal.html
I converted their proposed solutions to Ruby:
class Float
MY_EPSILON = 0.000000000000001
MY_TOLERANCE = 0.000000000000001
def eq_epsilon?(flt)
a = self
b = flt
(a - b).abs <= MY_EPSILON * a.abs
end
def self.reldif(a, b)
c = a.abs
d = b.abs
d = [c,d].max
d == 0.0 ? 0.0 : (a - b).abs / d
end
def eq_reldif?(flt)
Float.reldif(self, flt) <= MY_TOLERANCE
end
end
And thus we can run some test code:
f1 = 0.99999999999999998
f2 = 0.9999999999999998
f3 = 0.999999999999998
[f1, f2, f3].each { |f|
p f.eq_epsilon?(1.0)
p 1.0.eq_epsilon?(f)
}
puts "--------------"
[f1, f2, f3].each { |f|
p f.eq_reldif?(1.0)
p 1.0.eq_reldif?(f)
}
With output:
true
true
true
true
false
false
--------------
true
true
true
true
false
false
However more testing is probably needed to make sure it satisfies all your requirements.

Ruby Weighted Round Robin

I have an unknown number of things, let's say 100 apples that all have the same mass.
I have two buckets with total weights I'm trying to hit when all the apples are in the buckets - Bucket 1 with 60% of the total weight, and Bucket 2 with 40%.
I need a simple ruby algorithm to put the apples one by one into the buckets. I need to keep the two buckets as equally distributed as possible while I'm filling them up.
I will not be able to do this all at once, so I won't know which was the last apple to go into the last bucket. But I can always know the total number of apples in each bucket.
(This is a real problem I'm trying to solve, not a homework question - I'm just phrasing it this way so it will be easy to understand.)
Define a method to add items to two variables, according to the weighted rules supplied to the parameters:
def fill_with_ratio(weighting1, weighting2, items)
b1 = 0
b2 = 0
ratio = weighting1.fdiv weighting2
steps = []
#step 1 empty buckets
if b1 + b2 == 0
if ratio <= 1.0
b2 += 1
else
b1 += 1
end
end
steps << { step: 1, b1: b1, b2: b2, ratio: b1.fdiv(b2).round(2) }
#steps 2 to items
(items-1).times.with_index(2) do |_,i|
r1 = b1.succ.fdiv b2
r2 = b1.fdiv b2.succ
if (r1 - ratio).abs <= (r2 - ratio).abs
b1 += 1
else
b2 += 1
end
steps << { step: i, b1: b1, b2: b2, ratio: b1.fdiv(b2).round(2) }
end
steps
end
The if expressions decide which variables to increment by one in order to achieve the closest match to the defined distribution. The steps array only serves to show the steps after each addition. It can be omitted with no effect.
Key methods: Integer#fdiv, Integer#times, Enumerator#with_index, Integer#succ and Integer#abs.
Example One:
require 'pp' #pp prints everything nicely.
pp fill_with_ratio(60, 40, 100)
#[{:step=>1, :b1=>1, :b2=>0, :ratio=>0.0},
# {:step=>2, :b1=>1, :b2=>1, :ratio=>1.0},
# {:step=>3, :b1=>2, :b2=>1, :ratio=>2.0},
# {:step=>4, :b1=>2, :b2=>2, :ratio=>1.0},
# {:step=>5, :b1=>3, :b2=>2, :ratio=>1.5},
# .
# .
# .
# {:step=>98, :b1=>59, :b2=>39, :ratio=>1.51},
# {:step=>99, :b1=>59, :b2=>40, :ratio=>1.48},
# {:step=>100, :b1=>60, :b2=>40, :ratio=>1.5}]
Example Two:
pp fill_with_ratio(30, 40, 21)
#[{:step=>1, :b1=>0, :b2=>1, :ratio=>Infinity},
# {:step=>2, :b1=>1, :b2=>1, :ratio=>1.0},
# {:step=>3, :b1=>1, :b2=>2, :ratio=>0.5},
# {:step=>4, :b1=>2, :b2=>2, :ratio=>1.0},
# {:step=>5, :b1=>2, :b2=>3, :ratio=>0.67},
# {:step=>6, :b1=>3, :b2=>3, :ratio=>1.0},
# {:step=>7, :b1=>3, :b2=>4, :ratio=>0.75},
# {:step=>8, :b1=>3, :b2=>5, :ratio=>0.6},
# {:step=>9, :b1=>4, :b2=>5, :ratio=>0.8},
# {:step=>10, :b1=>4, :b2=>6, :ratio=>0.67},
# {:step=>11, :b1=>5, :b2=>6, :ratio=>0.83},
# {:step=>12, :b1=>5, :b2=>7, :ratio=>0.71},
# {:step=>13, :b1=>6, :b2=>7, :ratio=>0.86},
# {:step=>14, :b1=>6, :b2=>8, :ratio=>0.75},
# {:step=>15, :b1=>6, :b2=>9, :ratio=>0.67},
# {:step=>16, :b1=>7, :b2=>9, :ratio=>0.78},
# {:step=>17, :b1=>7, :b2=>10, :ratio=>0.7},
# {:step=>18, :b1=>8, :b2=>10, :ratio=>0.8},
# {:step=>19, :b1=>8, :b2=>11, :ratio=>0.73},
# {:step=>20, :b1=>9, :b2=>11, :ratio=>0.82},
# {:step=>21, :b1=>9, :b2=>12, :ratio=>0.75}]
bucket_1, bucket_2 = add_apple(bucket_1, bucket_2, percentage_ratio)
def add_apple(bucket_1, bucket_2, percentage_ratio)
if bucket_1 + bucket_2 == 0
if percentage_ratio >= 50.0
bucket_1 += 1
else
bucket_2 += 1
end
return bucket_1, bucket_2
end
if bucket_1.to_f * 100 / (bucket_1 + bucket_2) < percentage_ratio
bucket_1 += 1
else
bucket_2 += 1
end
return bucket_1, bucket_2
end

Calculating pi using iterations in ruby

For a school's assignment I am trying to calculate pi using the Gauss Legendre algorithm to test cpu efficiency.
Therefore, I have written a program in Ruby.
This program should iterate 500000000 times and display the the time used for it. But everytime it executes within a second.
My question:
Is there a better way to iterate so it really does repeat 500 million times and display pi and the time?
include Math
a = 1
b = 1/sqrt(2)
t = 0.25
p = 1
i = 0
imax = 500000000
start = Time.now
until i = imax
an = (a/2) + (b/2)
bn = sqrt(a) * sqrt(b)
tn = t - p * ((a-an) * (a-an))
pn = 2 * p
a = an
b = bn
t = tn
p = pn
i +=1
PI = ((a+b)*(a+b))/(4*t)
end
finish = Time.now
time = finish - start
puts PI
puts time
Start by not making i equal imax right away:
until i = imax
Should be
until i == imax
Even better, just do
500000000.times do
Instead of that line.
In addition to the issues raised by #Nick and #sawa your algorithm is flawed: the square root of the product of a and b is not equal to the product of the square roots of a and b.
In ruby:
include Math
a, b, t, p = 1, 1/sqrt(2), 0.25, 1
imax = 5
imax.times do |i|
an = (a+b) / 2
bn = sqrt(a * b)
tn = t - p * ((a-an) * (a-an))
pn = 2 * p
a, b, t, p = an, bn, tn, pn
pi = ((a+b)*(a+b))/(4*t)
printf "%d : %10.60f\n", i, pi
end
Running this gives me:
0 : 3.140579250522168575088244324433617293834686279296875000000000
1 : 3.141592646213542838751209274050779640674591064453125000000000
2 : 3.141592653589794004176383168669417500495910644531250000000000
3 : 3.141592653589794004176383168669417500495910644531250000000000
4 : 3.141592653589794004176383168669417500495910644531250000000000
So clearly you need more accuracy, hence BigDecimal. As this is your homework assignment I'll leave that up to you :-). (If unsure which variables to change, try all except i and imax. Also check out http://www.ruby-doc.org/stdlib-1.9.3/libdoc/bigdecimal/rdoc/BigDecimal.html)
Another thing you are doing wrong is assigning a constant PI within a loop. Although it is possible to reassign a constant, it is not correct to do so. Either use a variable or move the assignment to outside of the loop so that it would be assigned only once.
Even if I remove the assignment and print out the result for each iteration like this:
include Math
a = 1
b = 1/sqrt(2)
t = 0.25
p = 1
i = 0
imax = 500000000
until i == imax
an = (a/2) + (b/2)
bn = sqrt(a) * sqrt(b)
tn = t - p * ((a-an) * (a-an))
pn = 2 * p
a = an
b = bn
t = tn
p = pn
i +=1
puts ((a+b)*(a+b))/(4*t)
end
I get the wrong result. It goes like this:
-2.1244311544725596
-1.1383928808463357
-1.1265990444799223
-1.1265961703346379
-1.126596170334544
-1.126596170334544
... # very long repetition of the same number
-1.126596170334544
-1.126596170334544
NaN
NaN
... # NaN forever
Something must be wrong with your algorithm.

Generating pastel colors

I neeed to generate random color. But I need pstel ones. Not too dark, not too bright.
I can generate colors this way:
color = (1..3).to_a.map{ ( c = rand(255).to_s(16) ).size < 2 ? "0#{c}" : c }.to_s
But it will return colors from all palette.
Try this:
start_color = 128 # minimal color amount
total_offset = 64 # sum of individual color offsets above the minimal amount
'#' +
[0, rand(total_offset), rand(total_offset), total_offset].sort.each_cons(2).map{|a,b|
"%02x" % (start_color+b-a)
}.join
Actually, here's tiny Sinatra app that you can play with and see the results instantly:
require 'sinatra'
def get_pastel start_color, total_offset
'#' +
[0, rand(total_offset), rand(total_offset), total_offset].sort.each_cons(2).map{|a,b|
"%02x" % (start_color+b-a)
}.join
end
get '/:start_color/:total_offset' do |start_color, total_offset|
(0..20).map{c = get_pastel(start_color.to_i, total_offset.to_i)
"<span style='background-color:#{c}'>#{c}</span>\n"
}.join
end
Then fire up the browser and see how it looks:
http://localhost:4567/192/64
http://localhost:4567/128/128
;)
This might give you something useful:
colour_range = 128
colour_brightness = 64
color = (1..3).to_a.map{ ( c = rand(colour_range)+colour_brightness.to_s(16) ).size < 2 ? "0#{c}" : c }.to_s
I think it will limit you to mid saturation, mid-brightness colours.

Resources