2016-08-03 11 views
0

У меня есть следующая программа, которая должна учитывать количество лет, в течение которых население должно увеличиваться до нужного размера. Всякий раз, когда я запускаю это, я получаю бесконечный цикл. Может кто-нибудь помочь мне определить мою ошибку?Бесконечные Пока петли в рубине

def pop_growth(start, percent, desired)  
    year_count = 0 
    while start <= desired  
    year_count += 1 
    start = start + (start * (percent/100)) 
    end 
    return year_count 
end 
+0

Предполагая, что аргумент 'percent' является целым числом менее 100,' percent/100' будет равен нулю (целочисленное деление, помните?). Вам нужно 'percent/100.0', чтобы вернуть float, например 0.50. Кстати, учитывая ваш метод расчета, этот вопрос не имеет никакого отношения к 'inject', поэтому вы можете удалить его из заголовка. –

+0

@CarySwoveland, когда я прочитал ваш комментарий, я чувствовал себя обязанным дать ответ на основе 'inject' :) – mudasobwa

ответ

2

Я уверен, что вы пытаетесь с Целыми (вместо поплавков), так что вы теряете точность попробовать этот

def pop_growth(start, percent, desired)  
    year_count = 0 
    while start <= desired  
    year_count += 1 
    start = start + (start * (percent.to_f/100)) 
    end 
    return year_count 
end 

и дайте мне знать, если он работает для вас. если вы не можете отправить мне свой старт, проценты и желаемые значения?

2

Правильный ответ дается Орасио, позвольте мне переписать в идиоматических рубина:

def pop_growth start, percent, desired 
    (0..Float::INFINITY).inject(start) do |memo, years| 
    break years if memo > desired  
    memo *= (1.0 + percent/100.0) 
    end 
end 

или с бесконечным циклом:

def pop_growth start, percent, desired 
    loop.each_with_object(years: 0, count: start) do |_, memo| 
    break memo[:years] if memo[:count] > desired  
    memo[:years] += 1 
    memo[:count] *= (1.0 + percent/100.0) 
    end 
end 
2

Три пути.

# 1 Решить уравнение

Решить desired = start * (1.0 + 0.01 * percent)**n для n:

def pop_growth(start, percent, desired)  
    Math.log(desired.to_f/start)/Math.log(1.0 + percent/100.0) 
end 

years = pop_growth(100, 10, 200) 
    #=> 7.272540897341713 

years.ceil #=> 8 при желании.

# 2 Соединение до желания встретились

def pop_growth(start, percent, desired) 
    return 0 if start >= desired 
    alpha = 1.0 + 0.01 * percent 
    1.step.find { (start *= alpha) >= desired } 
end 

pop_growth 100, 10, 200 
    #=> 8 

# 3 Использование рекурсии

def pop_growth(start, percent, desired, years=0) 
    return years if start >= desired 
    pop_growth(start*(1.0+0.01*percent), percent, desired, years+1) 
end 

pop_growth 100, 10, 200 
    #=> 8 
+0

Приятно, но рассмотрим округление результата, так как' year_count' должен быть целым, AFAIU. – mudasobwa

+0

@ mudasobwa, мне не ясно, что требуется целое число («Я заплачу свою ипотеку за 8-1/2 года»), но я решил, что это должно быть 'pop_growth (100, 10, 200) .ceil # => 8', если требуется. –

0

Просто добавьте .to_f метод процента или разделить на 100.0, который преобразует число в поплавка ,

start + (start * (percent/100)) 

Когда вы разделяете, вы должны по крайней мере одно число с плавающей точкой, чтобы вернуть точный ответ деления, иначе Руби округлить его до ближайшего целого числа, которое в данном случае percent/100 приведет к 0, предполагая, что значение в процентах меньше 100. Это приведет к тому, что это утверждение start + (start * (percent/100)) станет start = start + 0, поэтому вы видите бесконечный цикл.

 Смежные вопросы

  • Нет связанных вопросов^_^