LINUX.ORG.RU

Помогите с простенькой программой на C++


0

1

Здавствуйте, изучаю потихоньку C++ по книге Бьерна Страуструпа. В конце каждой главы есть небольшие задания, в частности есть задачка на угадывание целого числа от 1 до 100 за максимум 7 попыток. Набрасал следующий код:

#include <iostream>
#include <string>
#include <cmath>
#include <vector>

double round(double number)
{
        return int(number + .5);
}
int main()
{
        std::vector<double> a(9);
        std::vector<std::string> s(8);
        a[0] = 105; s[0] = "???";
        a[1] = 50;
        std::string c = "???";
        std::cout << "Задумайте любое целое число от '1' до '100' \n" << "Программа будет задавать вопросы, если соглашаетесь введите 'y', иначе 'n'. \n";
        for (int i=0; i < 7; ++i)
            {
/*                      for (int k = 0; k < i+1; ++k)
                          {
                                          if (a[k] == a[i+1])
                                                    {
                                                                 s[i+1]=s[k];
                                                                 c = s[i+1];
                                                                 goto metka2;
                                                    }

                           }
*/
                      std::cout << i+1<<") Задуманное число меньше " << a[i+1] <<"? Ваш ответ: " ;
                      metka1:
                      std::cin >> c;
                      s[i+1] = c;
//                    metka2:
                      double r = a[i] - a[i+1];
                      double m = pow(r,2);
                      double m1 = pow(m,0.5);

                      if (c == "y")  a[i+2] = a[i+1] - m1/2; //*
                      else if (c  == "n") a[i+2] = a[i+1] + m1/2; //*
//                    if (c == "y")  a[i+2] = round(a[i+1] - m1/2);
//                    else if (c  == "n") a[i+2] = round(a[i+1] + m1/2);

                      else goto metka1;
           }

        std::cout << "\nВы задумали число " << round(a[8]) <<"\n"; //*
//      std::cout << "\nВы задумали число " << a[8] <<"\n";
        return 0;
}

Программа работает, но не так как мне хотелось бы, а хочется, чтобы вместо рациональных чисел она выводила целые в вопросах, но фокус с округлением не удался :( (случай если закоментировать строки, которые я обозначил «*», и раскоментировать те, что закоментены в приведённом примере). Что мне нужно изменить, чтобы добиться желаемого результата? Спасибо.

блин, не пиши такой хрени больше никогда.

anonymous ()

goto, односимвольные имена переменных, транслитерация имени метки, отсутствие проверки вводимых данных. Здорово.
А ты уверен что алгоритм верен? Неужели пользователь может загадать дробное число? Иначе, почему промежуточные значения у тебя могут быть дробными? Что-то тут не так.

jessey ()

Зачем вообще в задаче, где вся работа ведется с целыми числами, использовать типы с плавающей точкой?

delete83 ★★ ()
Ответ на: комментарий от Delirium_veritas

Ааааа, вон оно че... А разве нельзя было организовать алгоритм так, чтобы вообще не понадобилось никаких преобразований чисел? Я, конечно, сейчас точно не помню, но вроде в С/С++ есть целочисленное деление и половинное деление отрезка с известными верхней и нижней границей тоже вроде не сложно сделать...

delete83 ★★ ()
Ответ на: комментарий от delete83

А разве нельзя было организовать алгоритм так, чтобы вообще не понадобилось никаких преобразований чисел?

Нет, сходиться к ответу будет только на вещественных числах.

user_2190 ()
Ответ на: комментарий от Delirium_veritas

учитывая особенности IEEE754 вот ни разу не очевидно.

qnikst ★★★★★ ()

Что это за бред?

Попытка реализации бинарного поиска?

DELIRIUM ☆☆☆☆☆ ()

С такими талантами сразу надо писать на лиспе, бросай С++ и приобщайся к CL на lisper.ru.

anonymous ()

Забудьте о goto, как условных, так и безусловных. Навсегда.

Программу перепишите с нуля, с int вместо double.

AIv ★★★★★ ()
Ответ на: комментарий от delete83

А ты попробуй написать код, который реализует этот же метод деления отрезка пополам без использования типа с плавающей точкой и главное, чтобы программа работала. Буду даже очень рад если получится, честно,.. просто очень хочется на это посмотреть

hikkikamori ()
Ответ на: комментарий от anonymous

Причем здесь lisp? Очевидно прекрасная программа, не хватает только пары ассемблерных вставок для с-но телепатического угадывания числа, остальное обфускация же.

AIv ★★★★★ ()
Ответ на: комментарий от hikkikamori

Молодой человек (молодая человека?), Вы не поверите... эта задача решается именно в целых числах. Можно даже беззнаковых.

AIv ★★★★★ ()

Хм, хотел уж было начать читать код, чтоб подсказать, но увидел «goto metka2;». Нет, братан, не стоит тебе писать код на С++. Да и вообще писать код.

К слову, оформление самого кода у тебя тоже нехило так страдает.

Zhbert ★★★★★ ()

Программа работает, но не так как мне хотелось бы, а хочется, чтобы вместо рациональных чисел она выводила целые в вопросах

Можно так:

double round2(double number)
{
        double r = int(number);

        if (number > r)
            r += 1;

        return r;
}

std::cout << i+1<<") Задуманное число меньше " << round2(a[i+1]) << " - " << a[i+1] <<"? Ваш ответ: " ;

1. goto лучше заменить на if
2. Зачем хранить вектор? Можно хранить два последних числа.
3. Как уже сказали, вместо pow(pow(r,0.5),2) лучше использовать std::abs(r)

user_2190 ()
Ответ на: комментарий от AIv

пользуясь случаем. Библиотека для работы с разряженными массивами SuperLu [1]

в users guide должно быть описание всех используемых структур данных

--

[1] http://crd-legacy.lbl.gov/~xiaoye/SuperLU/

P.S. ТС тоже может попробовать использовать это тут, логичности реализации это не помешает.

qnikst ★★★★★ ()
Ответ на: комментарий от user_2190

3. Как уже сказали, вместо pow(pow(r,0.5),2) лучше использовать std::abs(r)

а если уж и использовать, (напр для проверки, что число является квадратом), то лучше sqrt(r)*sqrt(r)

qnikst ★★★★★ ()
Ответ на: комментарий от AIv

Молодой человек (молодая человека?), Вы не поверите... эта задача решается именно в целых числах. Можно даже беззнаковых.

Можете привести работающий код, чтобы в целых сошлось за 7 раз? :)

user_2190 ()
Ответ на: комментарий от Zorn

Как без них выйти из вложенных циклов, например, при возникновении _ошибки_

А вы знаете, чем (в частности) кресты отличаются от С?

anonymous ()
Ответ на: комментарий от qnikst

а что у ТС комплексные используются?

Гм, я про то, что не целые, а с плавающей точкой.

user_2190 ()
Ответ на: комментарий от qnikst

Как уже сказали, вместо pow(pow(r,0.5),2) лучше использовать std::abs(r)

fabs вообще то;-)

а если уж и использовать, (напр для проверки, что число является квадратом), то лучше sqrt(r)*sqrt(r)

Ааааа (стучусь головой об угол). Для целых чисел a/b==b && a%b==0

За ссылку спасибо, посмотрю;-)

AIv ★★★★★ ()
Ответ на: комментарий от AIv

Ааааа (стучусь головой об угол). Для целых чисел a/b==b && a%b==0

перебирать все b такие, что a%b==0? хотя согласен, что мой вариант не корректен

qnikst ★★★★★ ()
Ответ на: комментарий от user_2190

Можете привести работающий код, чтобы в целых сошлось за 7 раз? :)

Могу привести пример, в котором иногда и за 5 сходится!

#!/usr/bin/python
# -*- coding: utf-8 -*-

import sys
print 'А ну ка загадайте как че нить от 0 до 100!'
min, max = 0, 101
for i in range(7) :
    if raw_input( '%i: оно СТРОГО МЕНЬШЕ чем %i [y/любая другая фигня]?'%( i, (max+min)/2 ) )=='y' : max = (max+min)/2
    else : min = (max+min)/2
    if max-min<=1 : break
print 'я телепат, Вы задали', (max+min)/2

задание на дом - перевести это на С++ ;-)

AIv ★★★★★ ()
Ответ на: комментарий от user_2190

Не вижу в С++ разницы между abs и fabs.

#include <stdio.h>
#include <stdlib.h>
#include <math.h>

int main( int argc, const char** argv ) {
	double a = abs(1.5), b = fabs(1.5);
	printf("a=%g b=%g\n", a, b );
	return 0;
}

$ g++ test.cpp
$ ./a.out 
a=1 b=1.5

Так видно?

AIv ★★★★★ ()
Ответ на: комментарий от AIv

Хм, ЕМНИП все же работает, но завершит на все циклы пачкой, а только тот, в котором вызвано.

Ну тогда можно костыль прилепить, делов-то:

bool bContinue = true;
while(bContinue) {
  for(int i = 0; i < 100; i++) {
    if (i == 88) {
      bContinue = false;
      break;
    }
  }
}

Вместо первого фора использовать вайл в связке с && bContinue.

Zhbert ★★★★★ ()
Ответ на: комментарий от Zorn

А в C? )

Я на С не пишу, так что не в курсе... ;-(

Настоящий программист должен иметь толстую задницу, пустую голову, коротко остриженные ногти на правой руке, и не бояться условных переходов?;-)

AIv ★★★★★ ()
Ответ на: комментарий от Zhbert

даже только с break

 for (i;...) {
   for (j;...) {
     for (k;..) {
         if (eq) {
              smb_help_me = 1;
              break;
         }
     } 
     if (smb_help_me) break;
 if (smb_help_me) break;
 }

vs

for(i;...){
  for(j;...){
   for(k;...) {
     if (eq) { goto: velociraptor_dont_eat_me;}
   }
  }
}
velociraptor_dont_eat_me:

P.S. по этому поводу в яве хорошее решение

qnikst ★★★★★ ()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.