1

Тема: Жадібний касир "влітає в копійку"

Шановні форумчане, хелп  мі, плііз!
Задача: дати покупцеві рештуЮ використавши якнайменше монет. Монети номіналом 25, 10, 5, 1. Сумма, яку треба дати на решту, вводиться в гривнях ( 1.24, 0.56, .32, 1). Від`ємні значення не приймаються. Я на Сі написав отаке

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

int main (void)

{
    int i; //*s-sum залишок, *//
    float s, n;
    printf ("O hai! How mach change is owed?.\n");
    
    
    
    n = GetFloat ();
    
    
    for ( ; n <= 0; )
    {
       scanf ("%f", &n); 
    }
    
    
    
    s = n * 100;
    
    for (i = 0; s >=25; i ++)
    {
        s = s - 25;
    }
    
    for ( ; s >= 10; i ++)
    {
        s = s - 10;
    }
    
    for ( ; s >= 5; i ++)
    {
        s = s - 5;
    }
    
    for ( ; s >=1; i ++)
    {
        s = s - 1;
    }
    printf ("%d\n", i);
    return 0;
} 

Програмка начебто працює, але іноді дає отакі помилки :( input of 4.2 yields output of 18
   \ expected output, but not "22\n"
:( rejects a negative input like -.1
   \ expected output, not a prompt for input
Ніяк не можу зрозуміти де косяк і як його позбутись. Підкажіть, кто може!

2

Re: Жадібний касир "влітає в копійку"

А можна умову повністю навести, а не ваш переказ? Бо "від`ємні значення не приймаються" - це, звісно, чудово, але що має робити в цьому випадку програма? І чому в рядках 14 і 19 ви використовуєте різні функції - що, GetFloat не читає float, а щось інше робить?

Подякували: mityaev, varkon2

3 Востаннє редагувалося koala (10.02.2017 22:06:10)

Re: Жадібний касир "влітає в копійку"

А ось вам відповідь на вашу першу проблему: http://ideone.com/1eTmWA
У float-ів є межа точності. Округлюйте до цілого. І раджу скористатися цілим діленням і залишком, програма значно простіша буде.

Не заглядайте!
Подякували: mityaev, varkon2

4

Re: Жадібний касир "влітає в копійку"

koala написав:

А можна умову повністю навести, а не ваш переказ? Бо "від`ємні значення не приймаються" - це, звісно, чудово, але що має робити в цьому випадку програма? І чому в рядках 14 і 19 ви використовуєте різні функції - що, GetFloat не читає float, а щось інше робить?

Уявімо, що касир винен покупцю певну суму решти, а на поясі у нього знаходяться видавачі монеток номіналом 25¢, 10¢, 5¢ та 1¢.

Ми попросили вас використовувати  GetFloat  для того щоб ви могли зчитати долари і центи, хоча і без знаку долара. Іншими словами, якщо якомусь покупцеві винні $9.75 (як у випадку, коли газета коштує 25¢, а покупець розраховується $10 банкнотою), вважається, що введено буде  9.75, а не  $9.75 чи 975. Хай там як, навіть у випадку, якщо якомусь покупцеві потрібно видати рівно $9, вважається, що на вході має бути  9.00  або  9 але, знову ж таки, не $9 чи 900. Звичайно ж, за природою значень із плаваючою комою, ваша програма має працювати і з 9.0 та 9.000; вам не потрібно перейматися перевіркою того, чи користувач увів "форматовані" дані у вигляді, характерному для грошової суми. Вам також не треба перейматися чи введене значення не занадто велике, щоб поміститися у тип float. Але вам все ж таки доведеться перевірити чи у введеному є цент! Ем, тобто сенс. Використання лише GetFloat надає певності тільки в тому, що введені користувачем дані  мають дробову частину (або ж просто цілі), але не в тому, що вони невідємні. Якщо користувач вводить відємні значення, ваша програма має повторювати запит про введення правильного значення знову і знову, доки вимоги не будуть виконані.

5

Re: Жадібний касир "влітає в копійку"

#include <iostream>
using namespace std;
 
int main(){
    float  grn[] = {1.24, 0.56, .32, 1};
    size_t nom[] = {25, 10, 5, 1};//мають буди відсоротовані по зменшенню
    size_t grn_size = sizeof(grn) / sizeof(grn[0]);
    size_t nom_size = sizeof(nom) / sizeof(nom[0]);
    for( size_t i = 0; i < grn_size; i++ )
    {
        size_t dif = grn[i]*100;
        size_t cnt = 0;
        cout<<grn[i]<<" : "<<endl;
        for( size_t j = 0; dif && (j < nom_size); j++)
        {
            cnt = dif / nom[j];
            cout<<nom[j]<<" = "<<cnt<<endl;
            dif -= cnt*nom[j]; 
        }
    }
    return 0;
}

http://ideone.com/DgNPQH

1.24 :
25 = 4
10 = 2
5 = 0
1 = 4
0.56 :
25 = 2
10 = 0
5 = 1
1 = 1
0.32 :
25 = 1
10 = 0
5 = 1
1 = 2
1 :
25 = 4

6

Re: Жадібний касир "влітає в копійку"

Намагався округлити, але у мене не виходить  Конструкція round (c), где с - сума решти, що вводиться з GtnFloat не працює, а як по іншому округлити я не знаю, і запитати нема в кого.

koala написав:

А ось вам відповідь на вашу першу проблему: http://ideone.com/1eTmWA
У float-ів є межа точності. Округлюйте до цілого. І раджу скористатися цілим діленням і залишком, програма значно простіша буде.

Не заглядайте!

7

Re: Жадібний касир "влітає в копійку"

-=ЮрА=-, у вас 4.2 не працює: http://ideone.com/m2pRbj

8 Востаннє редагувалося -=ЮрА=- (11.02.2017 00:14:00)

Re: Жадібний касир "влітає в копійку"

Та все там працює, це ж від'ємні, як  ви лінкер налаштуєте так і буде 4.2 чи 4.19999
http://ideone.com/sL8JI7
взагалі завдання з від'ємними треба вирішувати у даблі
http://ideone.com/owCbcb
взагалі не бачу якихось вагомих причин мати одинарну точність, окрім випадку коли потрібно "тримати" багато від'ємних у меморі.

9

Re: Жадібний касир "влітає в копійку"

Панове, я зрозумів, що помилка через те, що не округлив до цілого. Але підкажіть, будь ласка, як мені після 18 рядка застосувати round () і округлити s до цілого. Чи якимось іншим чином це зробити? Дяую.

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

int main (void)

{
    int i; 
    float s, n;
    printf ("O hai! How mach change is owed?.\n");
    
    n = GetFloat ();
    
    for ( ; n <= 0; )
    {
     n =  GetFloat (); 
    }
    s = n * 100;
    for (i = 0; s >=25; i ++)
    {
        s = s - 25;
    }
    for ( ; s >= 10; i ++)
    {
        s = s - 10;
    }
    for ( ; s >= 5; i ++)
    {
        s = s - 5;
    }
    for ( ; s >=1; i ++)
    {
        s = s - 1;
    }
    printf ("%d\n", i);
    return 0;
} 

10

Re: Жадібний касир "влітає в копійку"

Вам же потрібні цілі числа копійок? От їх і використовуйте -

int s,nint;
nint = round(n);//надалі всі розрахунки ведуться із nint замість n

і for(;...;) - без першого і третього параметра - значно красивіше записується як while.

Подякували: mityaev1

11

Re: Жадібний касир "влітає в копійку"

Ураа! Запрацювало! Дякую.

12

Re: Жадібний касир "влітає в копійку"

А тепер переробіть із % та / замість циклів.

Подякували: varkon, mityaev2

13

Re: Жадібний касир "влітає в копійку"

Спробую