Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
 
Рейтинг 4.52/29: Рейтинг темы: голосов - 29, средняя оценка - 4.52
6 / 6 / 3
Регистрация: 14.11.2016
Сообщений: 53
1

Округление числа до n знаков после десятичной точки

10.01.2017, 07:09. Просмотров 5363. Ответов 10

Решил задачу для новичков по C++. Задача совсем для зелёных новичков, кто только-только начал изучать C++, и у меня есть ощущение, что её можно решить лучше. Нет ли каких-то замечаний по поводу моего решения? Нельзя ли её решить лучше, правильнее? Сражу скажу, что to_string использовать нельзя. Лично мне с моего непрофессионального взгляда кажется, что моё решение слишком длинное для такой элементарной задачи.

Задача:
Есть число: 2.7182818284590452353602875
Нужно округлить его до целых n.
Пример:
n=0, тогда ответ равен 3
n=25, ответ равен 2.7182818284590452353602875
n=13, ответ равен 2.7182818284590

Вот мой вариант: моё решение корректно, но, может быть, вы подскажите, как можно улучшить код.

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
#include <fstream>
#include <iostream>
using namespace std;
#include <stdlib.h>
#include <string>
#include <sstream>
 
int main(int argc, char* argv[])
{
    setlocale(LC_ALL, "rus"); // корректное отображение Кириллицы
    int i,c;
    string b="2.7182818284590452353602875";
        
    ifstream fin("input.txt"); // открыли файл для чтения
    ofstream fout("output.txt", ios_base::out | ios_base::trunc);
    fin >> i;
    if (i==0) {
        fout << 3;
        return 0;       
    }
    
    if (i==1){
        fout <<2.7;
        return 0;
    }
    
    if (i==25){
        fout << b;
        return 0;
    }
 
    c = b[i+2] - '0';   
    
    string answer;
    if (c<5){
        answer = b.substr(0,i+2);
    }
    else{
        ostringstream temp;
        int c = b[i+1] - '0';
        temp << c+1;
        string f = temp.str();
        answer = b.substr(0,i+1)+f;
    }
    
    
    fout << answer;   
  
    return 0;
}
0
Лучшие ответы (1)
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
10.01.2017, 07:09
Ответы с готовыми решениями:

Округление знаков, после точки
Столкнулся с проблемой при работе с float float x1 = 1.0000000000000000; float x2 = x1 +...

Округлить число до 25 знаков после десятичной точки
Есть простая задача: вот я ее решаю таким способом, т.к в задании написано округлить ...

Вычислить функцию с точностью 6 знаков после десятичной точки
)Вычислить функцию f(x,a)= при x=0.4, 0.6,..., 1.2 и a=2, 3, 4, 5 с точностью 6 знаков после...

Вывести в выходной файл округленное до n знаков после десятичной точки число E
Выведите в выходной файл округленное до n знаков после десятичной точки число E. Число Е,...

10
58 / 16 / 26
Регистрация: 07.02.2015
Сообщений: 336
10.01.2017, 16:11 2
Укоротить строку иначе говоря

Пока вспомнил только для double

1)Подключить заголовочный файл
C++
1
#include <iomanip>
Эта библиотека отвечает за наличие манипуляторов с параметрами.

2)Затем использовать
C++
1
setprecision(int count)
где count это количество цифр после запятой
Например
C++
1
cout<<fixed<<setprecision(3)<<b;
Слово
C++
1
fixed
отвечает что выводимое выражение будет фиксированным,после какого либо преобразования
1
Форумчанин
Эксперт CЭксперт С++
8160 / 5008 / 1436
Регистрация: 29.11.2010
Сообщений: 13,458
10.01.2017, 16:19 3
Цитата Сообщение от vjg2017 Посмотреть сообщение
Сражу скажу, что to_string использовать нельзя
А stringstream буфер можно? То есть то же самое, но чуть подлиннее.
Проблема в том, что при n = 25 у нас нет ни одного стандартного типа для хранения столь длинного числа с заданной точностью. Даже если рассматривать дробную часть как максимально возможное стандартное целое число (64 бита), получается 20-значное значение.
Тут нужна длинная арифметика. И либо массивы, либо строки (например, std::string). Но если to_string нельзя, то скорее всего вариант с решением на строках не подходит.
n точно никак не ограничен?

Добавлено через 38 секунд
Цитата Сообщение от redseven Посмотреть сообщение
Пока вспомнил только для double
double не позволяет хранить числа с точностью до 25 знаков после запятой.
1
Эксперт С++
3206 / 1733 / 435
Регистрация: 03.05.2010
Сообщений: 3,867
10.01.2017, 21:29 4
Лучший ответ Сообщение было отмечено vjg2017 как решение

Решение

Цитата Сообщение от vjg2017 Посмотреть сообщение
моё решение корректно
А вы не горячитесь в этом утверждении?
Мое решение:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
#include <iostream>
#include <string>
///////////////////////////////////////////////////////////////////////////////
typedef std::string     T_str;
///////////////////////////////////////////////////////////////////////////////
T_str   round_with_precision
    (
        T_str   const   &   s,
        size_t              n
    )
{
    const   char    POINT_SYMB  {'.'};
    const   char    ZERO_SYMB   {'0'};
 
    auto    s_cur       =   s;
    auto    point_pos   =   s_cur.find( POINT_SYMB );
 
    auto    n_cur       =   point_pos   ==  T_str::npos
                                ?   0
 
                                :       s_cur.size()
                                    -   1
                                    -   point_pos;
 
    if( n   <   n_cur )
    {
        auto    new_back_pos   =   point_pos + n + 1;
 
        s_cur.erase( ++new_back_pos );
        auto    is_rest     =   s_cur.back()    >=  '5';
        s_cur.pop_back();
 
        if( is_rest )
        {
            s_cur   =   ZERO_SYMB     +   s_cur;
 
            for (
                    int
                    p   =   s_cur.size() - 1;
                    p   >=  0;
                    --p
                )
            {
                if  (
                        s_cur[p]    ==  POINT_SYMB
                    )
                {
                    continue;
                }
 
                ++s_cur[p];
                s_cur[p]    -=  ZERO_SYMB;
                s_cur[p]    %=  10;
                s_cur[p]    +=  ZERO_SYMB;
 
                if  (
                        s_cur[p]    !=  ZERO_SYMB
                    )
                {
                    break;
                }
            }//for
 
            while   (
                            s_cur.front()   ==  ZERO_SYMB
                        &&  s_cur[1]        !=  POINT_SYMB
                    )
            {
                s_cur.erase(0, 1);
            }
        }//if is_rest
 
        if  (
                s_cur.back()    ==  POINT_SYMB
            )
        {
            s_cur.pop_back();
        }
    }//if
 
    return  s_cur;
}
///////////////////////////////////////////////////////////////////////////////
int     main()
{
    T_str   s   =   "2.7182818284590452353602875";
 
    for( int  i = 30 ; i >= 0; --i )
    {
        std::cout   <<  std::endl
                    <<  "n = "
                    <<  i
                    <<  std::endl
                    <<  round_with_precision( s, i )
                    <<  std::endl;
    }//for
}
1
6 / 6 / 3
Регистрация: 14.11.2016
Сообщений: 53
11.01.2017, 00:13  [ТС] 5
MrGluck,
"А stringstream буфер можно? То есть то же самое, но чуть подлиннее".
Я не знаю, я выбрал один сайт с интересными задачами, чтобы подучить язык. Задачки интересные, есть те, где нужно подумать (но они не слишком сложные, то есть некий баланс). Попробовал сдать задание с to_string -- не прошло. Мой вариант прошёл тесты, но стало интересно, а нельзя ли сделать задачу лучше. Например, я задал такой же вопрос по Java -- получил новые знания Оценить качество кода -- решение учебное задачи для начинающих В следующий раз, когда буду сдавать задачи по Java -- буду использовать те вещи, которые узнал.

"Но если to_string нельзя, то скорее всего вариант с решением на строках не подходит.
n точно никак не ограничен?"

Нет, n не ограничен. n может быть равен 25 максимум. Минимум -- 0.

Mr.X
"А вы не горячитесь в этом утверждении?
Мое решение:"


Чтобы ответить на ваш вопрос, мне нужно каким-то образом запустить вашу программу. Я для решение задач использую Dev-C++ 5.11.

Я скопировал ваш код -- попробовал запустить.

Получил ошибки:
1. main.cpp In function 'T_str round_with_precision(const T_str&, size_t)':

2. main.cpp [Warning] extended initializer lists only available with -std=c++11 or -std=gnu++11

3. 13 33 main.cpp [Warning] extended initializer lists only available with -std=c++11 or -std=gnu++11

4. 15 13 main.cpp [Error] 's_cur' does not name a type

5. 16 13 main.cpp [Error] 'point_pos' does not name a type

Если бы я мог запустить вашу программу, я дал ответ на ваш вопрос, но моя программа успешно прошла 20 тестов. Её засчитала автоматическая система. Я здесь разместил сообщение, потому что, может быть, узнаю что-то новое, что могу использовать на новых задачах.
0
Don't worry, be happy
16917 / 9794 / 1886
Регистрация: 27.09.2012
Сообщений: 24,283
Записей в блоге: 2
11.01.2017, 00:20 6
Цитата Сообщение от vjg2017 Посмотреть сообщение
Её засчитала автоматическая система
Ваше решение корректно только для нескольких частных случаев - не более.
1
Эксперт С++
3206 / 1733 / 435
Регистрация: 03.05.2010
Сообщений: 3,867
11.01.2017, 00:54 7
Цитата Сообщение от vjg2017 Посмотреть сообщение
Я здесь разместил сообщение, потому что, может быть, узнаю что-то новое
Цитата Сообщение от vjg2017 Посмотреть сообщение
-std=c++11
Ну, вот вам и новенькое!
1
6 / 6 / 3
Регистрация: 14.11.2016
Сообщений: 53
11.01.2017, 20:15  [ТС] 8
Правильно, так что и здесь я тоже что-то узнал для себя нового и полезного. Так что создал тему не просто так.

Добавлено через 19 часов 14 минут
Кстати, мне удалось улучшить свой первоначальный вариант (напомню, что условие задача -- не сократить произвольное число с n знаками, а только частный вариант с n=25 и числом, равным, 2.7182818284590452353602875). Я сумел сократить код своей задачи по числу линий почти в два раза:
было у меня -- 50 строк
Стало -- 27 строк.

То есть я нашёл более короткое решение задачи -- она прошла автоматическую проверку по 20 тестам:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#include <fstream>
#include <iostream>
#include <string>
using namespace std;
int main()
{
    string s = "2.7182818284590452353602875";
    int n;
    ifstream fin("input.txt");
    ofstream fout("output.txt", ios_base::out | ios_base::trunc);
    fin >> n;
    if (n==0){
          fout<<3;
    }
    else{
        for (int i=0;i<n+1;i++){
            fout <<s[i];
        }
        if (s[n+2]>'4'){
            fout<<(char)((int)s[n+1]+1);
        }
        else{
            fout <<s[n+1];
        }
    }
}
0
Форумчанин
Эксперт CЭксперт С++
8160 / 5008 / 1436
Регистрация: 29.11.2010
Сообщений: 13,458
11.01.2017, 20:54 9
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <iostream>
#include <string>
 
int main()
{
    std::string s = "2.7182818284590452353602875";
    int n;
    std::cin >> n;
    if (n != 0)
    {
        if (s[n+2] > '4')
            s[n+1]++;
        std::cout << s.substr(0, n+2);
    }
    else
        std::cout << 3;
}
Добавлено через 3 минуты
Решение на С (алсо работает для С++)
C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <stdio.h>
 
int main(void)
{
    char s[] = "2.7182818284590452353602875";
    int n;
    scanf("%d", &n);
    if (n != 0)
    {
        if (s[n+2] > '4')
            s[n+1]++;
        s[n+2] = '\0';
        printf("%s", s);
    }
    else
        printf("3");
    return 0;
}
1
Don't worry, be happy
16917 / 9794 / 1886
Регистрация: 27.09.2012
Сообщений: 24,283
Записей в блоге: 2
11.01.2017, 22:17 10
MrGluck, предлагаю проверить на строке
C
1
char s[] = "2.4444449";
1
Форумчанин
Эксперт CЭксперт С++
8160 / 5008 / 1436
Регистрация: 29.11.2010
Сообщений: 13,458
12.01.2017, 00:21 11
Croessmah, у ТС вполне конкретные условия. И я переписал его код выше, просто в более компактной форме.
0
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
12.01.2017, 00:21

Заказываю контрольные, курсовые, дипломные и любые другие студенческие работы здесь.

Выведите в выходной файл округленное до n знаков после десятичной точки число E
Как пишутся очень короткие программы на C++ или C (менее 150 символов, не считая пробелов и...

Округление числа до двух знаков после запятой
8. Написать программу, которая предлагает пользователю ввести дробное число, округляет его до двух...

Функция round(), округление числа до 4-х знаков после запятой
Вот наткнулся на проблемку как округлить число до 4 знаков после запятой? Подскажите что делать?

Округление числа в строке до указанного количества знаков после запятой
Как делать округление в строке, до знака после запятой порядковый номер который задаёт пользователь...

Функция, которая принимает в качестве параметров вещественное число и количество знаков после десятичной точки
Доброго вечера,подскажите пожалуйста как можно решить задачку,(существует функция, которая...

Число знаков после десятичной точки
Хочу узнать как можно записать число 5.75533673 например , с тремя знаками после точки


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
11
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2021, vBulletin Solutions, Inc.