Форум программистов, компьютерный форум CyberForum.ru
Наши страницы

С++ для начинающих

Войти
Регистрация
Восстановить пароль
 
 
Рейтинг: Рейтинг темы: голосов - 28, средняя оценка - 4.75
Hi4ko
74 / 74 / 4
Регистрация: 21.10.2010
Сообщений: 376
#1

Округление double - C++

20.10.2011, 22:45. Просмотров 3896. Ответов 15
Метки нет (Все метки)

Короче ввожу число 1.05
в Debug показывает его, как 1.004999999999999999995663191310058
вот как эту чушь убрать, у меня задача из-за этого не решается?
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
20.10.2011, 22:45
Здравствуйте! Я подобрал для вас темы с ответами на вопрос Округление double (C++):

Округление Double - C++
Использую Double, возникают при тонких расчетах проблемы с округлением. Какие есть стандартные способы решения? :)

Округление Long double. - C++
Нужно округлить число типа long double в меньшую сторону т.е. просто обнулить всю дробную часть, но при этом надо сохранить эту самую...

Убрать округление double - C++
Доброго времени суток! Недавно начав самостоятельно изучать С++, я пыталась выполнить лабораторную работу по созданию программы для...

Форматирование вывода и округление double - C++
Доброго времени суток. Я много подобных тем полистал. Но не нашел ответа. Мне нужно написать функцию, которая бы получала double число,...

double округление с точность до N знаков - C++
Добрый день, помогите пожалуста какую надо использовать функцию чтобы была возможность округлить значение числа double с точностью до N...

printf. Округление чисел типа double - C++
Пытаюсь писать программу для округления чисел типа double. // okruglenie double.cpp: определяет точку входа для консольного...

15
Bers
Заблокирован
20.10.2011, 22:52 #2
если дробная часть не является степенью с основанием 2, то машина будит не в состоянии запомнить его без погрешности.

Либо запоминай дробь в виде двух чисел, либо в видет текста, либо учитывай погрешность.

Дробные числва нельзя сравнивать друг с другом. Можно сравнивать лишь разность этих чисел с погрешностью.


if(a-b< p) { /*считать числа a и b равными*/ }
где p - очень маленькое число, и гарантированно, что это незначительное расхождение между а и б - допустимое что бы считать их равными
0
Hi4ko
74 / 74 / 4
Регистрация: 21.10.2010
Сообщений: 376
20.10.2011, 23:00  [ТС] #3
Цитата Сообщение от Bers Посмотреть сообщение
если дробная часть не является степенью с основанием 2, то машина будит не в состоянии запомнить его без погрешности.

Либо запоминай дробь в виде двух чисел, либо в видет текста, либо учитывай погрешность.

Дробные числва нельзя сравнивать друг с другом. Можно сравнивать лишь разность этих чисел с погрешностью.


if(a-b< p) { /*считать числа a и b равными*/ }
где p - очень маленькое число, и гарантированно, что это незначительное расхождение между а и б - допустимое что бы считать их равными
Ну тогда уж сразу помогите с реализацией задачи

считывают 3 числа: A,B,C типа double

надо вывести, сколько раз k*A/B является целым(k*A<C), где k - переменная, увеличивающаяся на 1 при каждой проверке

У меня проверялось,
C++
1
2
3
4
5
6
7
     
    while(k*A<С)
    {
        if(floor(k*A/B)==C/B)
            ++sum;
        ++k;
    }
А если там 1.049999999.... , то это не срабатывает, естественно. Что мне делать?
0
Bers
Заблокирован
20.10.2011, 23:02 #4
не вразумел условие задачи
0
grizlik78
Эксперт С++
1964 / 1457 / 119
Регистрация: 29.05.2011
Сообщений: 3,016
21.10.2011, 19:20 #5
Если числа надо сравнивать, то по возможности следует использовать целочисленные типы. Но если уж числа изначально дробные и представлены типом double, то обычно проверяют модуль их разности на превышение некого разумного порога.
C++
1
2
3
4
if ( fabs(y - x) < 1.e-7)
    ; // is equal
else
    ; // is not equal
Порог прямо зависит от порядка сравниваемых чисел, так как ошибка представления больших чисел может на много порядков превосходить ошибку представления маленького числа (да и само это число).
1
Байт
Эксперт C
16326 / 10602 / 1587
Регистрация: 24.12.2010
Сообщений: 20,210
21.10.2011, 19:26 #6
Может быть пойти таким путем
C
1
2
double eps = 1.e-7;
if (fabs(y/x-1)<eps) ....
0
Bers
Заблокирован
21.10.2011, 19:34 #7
Цитата Сообщение от Байт Посмотреть сообщение
Может быть пойти таким путем
делить зачем? если можно просто вычесть? Деление - самая дорогая ариф. операция жеж
0
grizlik78
Эксперт С++
1964 / 1457 / 119
Регистрация: 29.05.2011
Сообщений: 3,016
21.10.2011, 19:43 #8
Зато ошибка представления числа при делении почти не зависит от абсолютного значения, так как в этом случае она получается почти в буквальном смысле относительной. Но тут ещё надо будет икс на ноль проверять.
0
odip
Эксперт С++
7158 / 3220 / 59
Регистрация: 17.06.2009
Сообщений: 14,164
21.10.2011, 19:51 #9
Не ясно условие задачи
надо вывести, сколько раз k*A/B является целым(k*A<C), где k - переменная, увеличивающаяся на 1 при каждой проверке
if(floor(k*A/B)==C/B)
Какие образом эта проверка выявит что k*A/B - целое число ?
Почему сравнивается именно с C/B, если нужно получить целое число ?

Вообще говоря пусть double t= k*A/B;
Нужно проверить что t - целое число
Так как полного совпадения с целым добиться крайне трудно то будем проверять что число t является целым с какой-то точностью eps ( eps= 0.001 )
Для простоты предположим что A>0, B>0, C>0
Тогда целая часть t - это floor(t)
Дробная часть t - это t-floor(t)
Нам нужно проверить что дробная часть t меньше eps
Условие такое:
if ( fabs( t-floor(t) )<eps ) ...

Добавлено через 3 минуты
Код примерное такой

C
1
2
3
4
5
6
7
8
9
10
double A,B,C, eps= 0.001;
double t;
int count= 0, k;
 
for ( k= 0; k*A<C; k++ ) {
    t= k*A/B;
    if ( fabs( t-floor(t) )<eps ) { count++; }
}
 
printf( "answer=%d\n", count );
0
Bers
Заблокирован
21.10.2011, 19:53 #10
я брал за погрешность const double ESP=0.0000001;
И никада не парился.

Этой погрешности и простого вычитания достаточно, что бы безошибочно запоминать числа
от -999999999.999999 до 999999999.999999

(использовал при написании велосипеда, который переводит символьное представление дробного числа в double и обратно. Аналоги из стандартной библиотеки работают с такой же максимальной точностью).
0
odip
Эксперт С++
7158 / 3220 / 59
Регистрация: 17.06.2009
Сообщений: 14,164
21.10.2011, 19:57 #11
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
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
 
 
 
int main( int argc, char *argv[] ) {
 
double A,B,C, eps;
double t;
int count= 0, k;
 
 
argc--; argv++;
if ( argc != 4 ) {
    fprintf( stderr, "usage: prog A B C eps\n" );
    exit( 2 );
}
A= atof( argv[0] );
B= atof( argv[1] );
C= atof( argv[2] );
eps= atof( argv[3] );
 
for ( k= 0; k*A<C; k++ ) {
    t= k*A/B;
    if ( fabs( t-floor(t) )<eps ) {
    count++;
    printf( "k=%d t=%-10f\n", k, t );
    }
}
 
printf( "answer=%d\n", count );
 
return 0;
 
} /* main() */
Код
> 1.exe 1 7 100 0.000001
k=0 t=0.000000
k=7 t=1.000000
k=14 t=2.000000
k=21 t=3.000000
k=28 t=4.000000
k=35 t=5.000000
k=42 t=6.000000
k=49 t=7.000000
k=56 t=8.000000
k=63 t=9.000000
k=70 t=10.000000
k=77 t=11.000000
k=84 t=12.000000
k=91 t=13.000000
k=98 t=14.000000
answer=15
0
Xaker ONeiLL
-1 / 2 / 0
Регистрация: 20.10.2011
Сообщений: 18
21.10.2011, 20:20 #12
if ( fmod(k*a, b) == 0 ) { /*если k*a делится на b без остачи чтото делаем*/ }

Добавлено через 11 минут
А если с учотом погрешности, то пиши


if(fmod(k*a, b) < 0.000001 ) { /*если k*a делится на b без остачи чтото делаем*/ }
0
Hi4ko
74 / 74 / 4
Регистрация: 21.10.2010
Сообщений: 376
21.10.2011, 22:54  [ТС] #13
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <iostream>
#include <cmath>
using namespace std;
int main()
{
  long  double A,L,B,k=1;
    int sum=0;
    cin>>L>>A>>B;
    while(k*A<L)
    {
        if(fmod(k*A,B)< 1.e-7)
            ++sum;
        k+=1;
    }
    cout<<sum;
}
Проверяется задача, на многих тестах пишет, что превышен лимит времени(2 секунды).
Из-за чего это может быть? Предел числам не указан
0
Bers
Заблокирован
21.10.2011, 22:55 #14
по кнопкам быстрее щёлкать нада))

 Комментарий модератора 
Избегайте грамматических ошибок при написании сообщений - уважайте себя и других участников форума.
Запрещено использовать нецензурные выражения в любом виде, оскорблять других участников форума, умышленно использовать выражения, противоречащие правилам русского языка.
Правила форума
Последнее предупреждение. Есть правила, и нужно их соблюдать независимо от того, нравится вам это, или нет.
0
odip
Эксперт С++
7158 / 3220 / 59
Регистрация: 17.06.2009
Сообщений: 14,164
22.10.2011, 09:40 #15
Проверяется задача, на многих тестах пишет, что превышен лимит времени(2 секунды).
Из-за чего это может быть? Предел числам не указан
Надо полагать это олимпиадная задача ?
0
22.10.2011, 09:40
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
22.10.2011, 09:40
Привет! Вот еще темы с ответами:

Округление числа double до десятых, до сотых - C++
Приветствую всех, double y=3.1415; нужно округлить y до десятых и сотых, записать в переменные соответственно. т.е. получить 0.1 и...

Ошибки error C2296: -: недопустимо, левый операнд имеет тип "double (__cdecl *)(double,double,double - C++
Думаю из-за polp #include&lt;iostream&gt; #include&lt;cmath&gt; #include&lt;cstdlib&gt; using namespace std; double polp(double af,double...

Ошибка: error LNK2001: unresolved external symbol "double __cdecl Akk(double,double,double)" - C++
#include &lt;iostream&gt; #include &lt;cmath&gt; using namespace std; double Akk(double x, double y, double z); int main() { int a, b, c; ...

Почему мы пишем double x (double y)? а не через запятую double x,y - C++
почему мы пишем double x (double y)? а не через запятую double x,y


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

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

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