Project

General

Profile

Bug #6974 » cn_ruby_sc_1r9r3_bug_hwm_10_run.rb

run program - jks (john sikora), 09/04/2012 12:00 PM

 
# this program calculates the Continued Fraction Expansion (CFE) of Champernowne's Constant
# (in base 10) to HWM #10. For HWM #10, it works in Ruby 1.9.2 but not in 1.9.3.
# HWMs #5 to #9 still work in 1.9.3.
# https://docs.google.com/file/d/0B_ZIuCD9HzQtaG5QOEc5dmZ1aFU/edit?pli=1
# (On the High Water Mark Convergents of Champernowne's Constant in Base Ten).
# also Google "Champernowne's Constant". Wikipedia or Wolfram MathWorld entries are helpful.


require 'bigdecimal'
include Math

def get_denominator_string(hwm_num) # get the denominator.
exponent = num_correct_digits(hwm_num - 1) + 2 * (hwm_num - 2) - 3
mantissa = '4.' + '9' * (hwm_num - 4) + '0' * (hwm_num - 3) + '5'
mantissa + 'E' + exponent.to_s
end

def num_correct_digits(hwm_num) # get the number of correct digits calculated by the convergent before the given HWM.
(hwm_num - 3)*10**(hwm_num - 3) - (1..(hwm_num - 4)).inject(0){|sum, int| sum + 10**int} - (hwm_num - 2)
end

puts; puts RUBY_VERSION


hwm = 10 # 5-10. 10 works in 1.9.2 but not in 1.9.3. for 5-9, works in both.
num_match = 10**(hwm - 4) - 1 # change to 9, 99, 999, etc. for constructing champ number to mult denom by.

t = []
t[0] = Time.now.to_f

champ_num_string = '0.'
for int in 1..num_match # using inject takes about the same amount of time as doing it this way.
champ_num_string += int.to_s
end
champ_num_string += '1' # add a 1 on the end as the first number in 10, 100, 1000, etc, so ceil gives correct numerator.
t[t.length] = Time.now.to_f
print "Time to make Champ Number: #{t[t.length - 1] - t[t.length - 2]}\n"

denominator = BigDecimal.new(get_denominator_string(hwm))
champ_num = BigDecimal.new(champ_num_string)
t[t.length] = Time.now.to_f
print "Time to make Champ Number and denom into bigdecimal: #{t[t.length - 1] - t[t.length - 2]}\n"
n = (champ_num * denominator).ceil
t[t.length] = Time.now.to_f
print "Time to calculate and ceil numerator: #{t[t.length - 1] - t[t.length - 2]}\n"

File.open("./cn_numer_before_hwm_#{hwm.to_s}_sc_ruby_ver_#{RUBY_VERSION.gsub('.', 'r')}_test.txt", "w") do |f|
f.puts n
end
t[t.length] = Time.now.to_f
print "Time to write numerator: #{t[t.length - 1] - t[t.length - 2]}\n"

d = (denominator + 1).to_i # have to add 1 or it returns infinity for HWM #10.
d -= 1 # subtract 1 to set it back to what it should be.

File.open("./cn_denom_before_hwm_#{hwm.to_s}_sc_ruby_ver_#{RUBY_VERSION.gsub('.', 'r')}_test.txt", "w") do |f|
f.puts d
end
t[t.length] = Time.now.to_f
print "Time to make denom into integer and write: #{t[t.length - 1] - t[t.length - 2]}\n"

####### the numerator and denominator are calculated and stored correctly for all HWMs (#5 through #10) in both 1.9.2 and 1.9.3 so the problem seems to be after this.

File.open("./cn_cfe_coeffs_before_hwm_#{hwm.to_s}_sc_ruby_ver_#{RUBY_VERSION.gsub('.', 'r')}_test.txt", "w") do |f|
num_coeffs = 0 # get CFE coefficients.
while d != 1 && num_coeffs < 5000 # should stop at 4837 for HWM #10, but it does not in 1.9.3.
if d == 0
puts 'error - numerator and denominator not in lowest terms.' # this should never happen as the CFE is guaranteed to be in lowest terms.
exit
end

q = n / d
d, n = n - d*q, d # flip n and d. using modulo is slower.
# print num_coeffs, ' ', q, "\n"
f.print num_coeffs, " ", q, "\n"

if d == 1 # if d=1, n is the last coefficient.
if num_coeffs % 2 == 0 # last coeff is not 1. we know hwm is on an even term (since calc num is larger than champ num). if num_coeffs is even, we know the last term (n) is not 1.
f.print num_coeffs + 1, " ", n, "\n"
else # last coeff is 1.
f.print num_coeffs + 1, " ", n - 1, "\n"
f.print num_coeffs + 2, " 1\n"
end
end

num_coeffs += 1
end
end
t[t.length] = Time.now.to_f
print "Time to calc and write coefficients: #{t[t.length - 1] - t[t.length - 2]}\n"

t[t.length] = Time.now.to_f
print "Total time: #{t[t.length - 1] - t[0]}\n"


(1-1/2)