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

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

Восстановить пароль Регистрация
 
Рейтинг: Рейтинг темы: голосов - 28, средняя оценка - 4.75
Hi4ko
74 / 74 / 4
Регистрация: 21.10.2010
Сообщений: 376
20.10.2011, 22:45     Округление double #1
Короче ввожу число 1.05
в Debug показывает его, как 1.004999999999999999995663191310058
вот как эту чушь убрать, у меня задача из-за этого не решается?
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
Bers
Заблокирован
20.10.2011, 22:52     Округление double #2
если дробная часть не является степенью с основанием 2, то машина будит не в состоянии запомнить его без погрешности.

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

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


if(a-b< p) { /*считать числа a и b равными*/ }
где p - очень маленькое число, и гарантированно, что это незначительное расхождение между а и б - допустимое что бы считать их равными
Hi4ko
74 / 74 / 4
Регистрация: 21.10.2010
Сообщений: 376
20.10.2011, 23:00  [ТС]     Округление double #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.... , то это не срабатывает, естественно. Что мне делать?
Bers
Заблокирован
20.10.2011, 23:02     Округление double #4
не вразумел условие задачи
grizlik78
Эксперт C++
 Аватар для grizlik78
1882 / 1414 / 101
Регистрация: 29.05.2011
Сообщений: 2,958
21.10.2011, 19:20     Округление double #5
Если числа надо сравнивать, то по возможности следует использовать целочисленные типы. Но если уж числа изначально дробные и представлены типом double, то обычно проверяют модуль их разности на превышение некого разумного порога.
C++
1
2
3
4
if ( fabs(y - x) < 1.e-7)
    ; // is equal
else
    ; // is not equal
Порог прямо зависит от порядка сравниваемых чисел, так как ошибка представления больших чисел может на много порядков превосходить ошибку представления маленького числа (да и само это число).
Байт
 Аватар для Байт
13974 / 8805 / 1227
Регистрация: 24.12.2010
Сообщений: 15,949
21.10.2011, 19:26     Округление double #6
Может быть пойти таким путем
C
1
2
double eps = 1.e-7;
if (fabs(y/x-1)<eps) ....
Bers
Заблокирован
21.10.2011, 19:34     Округление double #7
Цитата Сообщение от Байт Посмотреть сообщение
Может быть пойти таким путем
делить зачем? если можно просто вычесть? Деление - самая дорогая ариф. операция жеж
grizlik78
Эксперт C++
 Аватар для grizlik78
1882 / 1414 / 101
Регистрация: 29.05.2011
Сообщений: 2,958
21.10.2011, 19:43     Округление double #8
Зато ошибка представления числа при делении почти не зависит от абсолютного значения, так как в этом случае она получается почти в буквальном смысле относительной. Но тут ещё надо будет икс на ноль проверять.
odip
Эксперт C++
 Аватар для odip
7225 / 3287 / 58
Регистрация: 17.06.2009
Сообщений: 14,165
21.10.2011, 19:51     Округление double #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 );
Bers
Заблокирован
21.10.2011, 19:53     Округление double #10
я брал за погрешность const double ESP=0.0000001;
И никада не парился.

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

(использовал при написании велосипеда, который переводит символьное представление дробного числа в double и обратно. Аналоги из стандартной библиотеки работают с такой же максимальной точностью).
odip
Эксперт C++
 Аватар для odip
7225 / 3287 / 58
Регистрация: 17.06.2009
Сообщений: 14,165
21.10.2011, 19:57     Округление double #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
Xaker ONeiLL
-1 / 2 / 0
Регистрация: 20.10.2011
Сообщений: 18
21.10.2011, 20:20     Округление double #12
if ( fmod(k*a, b) == 0 ) { /*если k*a делится на b без остачи чтото делаем*/ }

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


if(fmod(k*a, b) < 0.000001 ) { /*если k*a делится на b без остачи чтото делаем*/ }
Hi4ko
74 / 74 / 4
Регистрация: 21.10.2010
Сообщений: 376
21.10.2011, 22:54  [ТС]     Округление double #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 секунды).
Из-за чего это может быть? Предел числам не указан
Bers
Заблокирован
21.10.2011, 22:55     Округление double #14
по кнопкам быстрее щёлкать нада))

 Комментарий модератора 
Избегайте грамматических ошибок при написании сообщений - уважайте себя и других участников форума.
Запрещено использовать нецензурные выражения в любом виде, оскорблять других участников форума, умышленно использовать выражения, противоречащие правилам русского языка.
Правила форума
Последнее предупреждение. Есть правила, и нужно их соблюдать независимо от того, нравится вам это, или нет.
odip
Эксперт C++
 Аватар для odip
7225 / 3287 / 58
Регистрация: 17.06.2009
Сообщений: 14,165
22.10.2011, 09:40     Округление double #15
Проверяется задача, на многих тестах пишет, что превышен лимит времени(2 секунды).
Из-за чего это может быть? Предел числам не указан
Надо полагать это олимпиадная задача ?
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
23.10.2011, 19:15     Округление double
Еще ссылки по теме:

Убрать округление double C++
Почему перестает работать программа при замене double на long double? C++
Почему мы пишем double x (double y)? а не через запятую double x,y C++

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

Или воспользуйтесь поиском по форуму:
Hi4ko
74 / 74 / 4
Регистрация: 21.10.2010
Сообщений: 376
23.10.2011, 19:15  [ТС]     Округление double #16
Цитата Сообщение от odip Посмотреть сообщение
Надо полагать это олимпиадная задача ?
да. В основу берётся проверка деления нацело десятичных дробей. Только в этом проблема.
До сих пор не могу решить её(
Yandex
Объявления
23.10.2011, 19:15     Округление double
Ответ Создать тему
Опции темы

Текущее время: 09:23. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2016, vBulletin Solutions, Inc.
Рейтинг@Mail.ru