Модераторы: Daevaorn
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Дробная часть double в int, и тут проблема 
V
    Опции темы
oper54
  Дата 22.5.2006, 12:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 217
Регистрация: 13.5.2005

Репутация: 1
Всего: 1



Доброе время суток.
Суть задачи:
Есть число тип double, надо его дробную часть перевсетив int.
Тоесть double( 121,322 ) = int( 322 )
Напсал я фун-цию, вроде все правильно и вот какой баг
int qpart( double, int& ) - если в double передать (0,21) то все ок,
а если передать 1,21 то функция уходт в вечный цикл....
Думал это баг gcc, компилил только что в VC 6.0 тот-же результат
Объясните что я не правильно делаю...  smile 
Вот собственно код
Код

#include<stdio.h>

int qpart( double dval, int &i ){
    int len( 0 );
    
    dval -= ( int )( dval );
    if( 0 == dval ) return len;
    while( ( dval - i ) != 0  ){
        i = ( int )( dval *= 10 );
        printf( "dval=%f\t\ti=%i\n", dval, i );
        len++;
    }
    return len;
}

int main( int argc, char* argv[] ){
    int    i;

    qpart( .2133, i );
    printf( "i = %i\n", i );
    return 0;
}


 
PM MAIL   Вверх
Earnest
Дата 22.5.2006, 12:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 5962
Регистрация: 17.6.2005
Где: Рязань

Репутация: 53
Всего: 183



С отладчиком умеем работать? Так посмотри, почему программа из цикла не выходит.
Скорее всего, из-за невыполнения условия: нельзя сравнивать double-значения точно, и надеяться, что будет работать. А сравнивать надо так: fabs(a-b) <= eps, где в качестве eps можно выбрать, например, MIN_FLOAT. 


--------------------
...
PM   Вверх
oper54
Дата 22.5.2006, 13:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 217
Регистрация: 13.5.2005

Репутация: 1
Всего: 1



Earnest, за пример сравнения спасибо конечно..
только я понимаю что нельза сравнивать double и int, 
поэтому вот и пишу while( ( dval - i ) != 0  ) - так можно,
проблемма вовсе не в этом
вот в чем проблемма

...
printf( "dval=%f\t\ti=%i\n", dval, i );
...

результат
dval=2.100000           i=2
dval=21.000000          i=20
dval=210.000000         i=209 
PM MAIL   Вверх
Earnest
Дата 22.5.2006, 13:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 5962
Регистрация: 17.6.2005
Где: Рязань

Репутация: 53
Всего: 183



Цитата(oper54 @  22.5.2006,  14:17 Найти цитируемый пост)
только я понимаю что нельза сравнивать double и int,

Не понимаешь похоже.  smile Это ты можешь сравнивать double и int, а компилятор может сравнивать только одинаковые типы. Т.е. он выполняет преобразование, в данном случае к double.

Цитата(oper54 @  22.5.2006,  14:17 Найти цитируемый пост)
while( ( dval - i ) != 0  ) - так можно,

Уверен? Что это, как не сравнение double. Может ты думаешь, что здесь инты сравниваются?

Цитата(oper54 @  22.5.2006,  13:14 Найти цитируемый пост)
функция уходт в вечный цикл....

Я, собственно, об этом.

Цитата(oper54 @  22.5.2006,  14:17 Найти цитируемый пост)
dval=210.000000         i=209  

А вот это уже совсем другая проблема... То, что выглядит как 210, вполне может на самом деле быть 209,9999999... Но это я могу только гадать, а у тебя, повторяю, отладчик есть. Вот и посмотри.
 


--------------------
...
PM   Вверх
oper54
Дата 22.5.2006, 13:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 217
Регистрация: 13.5.2005

Репутация: 1
Всего: 1



Цитата

Уверен? Что это, как не сравнение double. Может ты думаешь, что здесь инты сравниваются?

не я уверен что там будит double сравниаться с "0"
Цитата

Цитата(oper54 @  22.5.2006,  14:17 )    
dval=210.000000         i=209    

А вот это уже совсем другая проблема... То, что выглядит как 210, вполне может на самом деле быть 209,9999999... Но это я могу только гадать, а у тебя, повторяю, отладчик есть. Вот и посмотри.

отладчик выдает тоже самое что и printf...
если ты про асм то я на низком уровне не с машиной не общаюсь smile
Тут вот какая странность что если в фу-цию передать не 1,21 а 0,21 то все в порядке....

П.С. такая простая задачка, а я уже два дня торможу 
PM MAIL   Вверх
Earnest
Дата 22.5.2006, 14:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 5962
Регистрация: 17.6.2005
Где: Рязань

Репутация: 53
Всего: 183



Так с чего ты взял, что твой double 0 точно равен? А сравниваешь на точное равенство.
У тебя вообще строка "dval=210.000000         i=209"  не должна печататься по логике алгоритма - программа должна выйти их цикла на предыдущей итерации. Но не выходит. Потому что не срабатывает условие. Потому что оно не правильно написано.

!!!!!!

Добавлено @ 14:11 
И нечего мучаться над разной работой с 1,21 и 0,21. Это в десятичном представлении они похожи. А в двоичном (как их компьютер видит) - ничего общего. 


--------------------
...
PM   Вверх
Romikgy
Дата 22.5.2006, 14:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Любитель-программер
****


Профиль
Группа: Участник Клуба
Сообщений: 7326
Регистрация: 11.5.2005
Где: Porto Franco Odes sa

Репутация: 8
Всего: 146



dval=2.133000           i=2
dval=21.330000          i=21
dval=213.300000         i=213
dval=2133.000000                i=2132
dval=21330.000000               i=21330
i = 21330
У меня такой результат от исходника из первого поста, че нужно то?

Добавлено @ 14:39 
и чем floor и ceil не подходят?

Добавлено @ 14:50 
Код

#include<stdio.h>
#include <conio.h>
#include <math.h>
int qpart( double dval, int &i ){
    int len( 0 );
    long temp=0;
    dval -= ( int )( dval );
    if( 0.0 == dval ) return len;
    while( ( dval - (double)temp ) != 0.0  ){
        temp = (long)floor( dval *= 10 );
        printf( "dval=%f\t\ti=%i\n", dval, temp );
        len++;
    }
    i=(int)temp;
    return len;    
}
int main( int argc, char* argv[] ){    
    int    i;
    qpart( .2133, i );
    printf( "i = %i\n", i );
    getch();
    return 0;
}


Может так те подойдет? 


--------------------
Владение русской орфографией это как владение кунг-фу — истинные мастера не применяют его без надобности. 
smile

PM   Вверх
oper54
Дата 22.5.2006, 15:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 217
Регистрация: 13.5.2005

Репутация: 1
Всего: 1



 smile  smile  smile  НИЧЕГО НЕ ПОЛУЧАЕТЬСЯ!!!!!!  smile  smile  smile 

Romikgy, проблема в том что если в ф-цию передать 0,2123 то все ок, а если передать что то вроде 654,2123 не работает!
Еще один вариант и все равно не работает ( Earnest +  Romikgy ).....
Код

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

const double MIN_DOUBLE        = 0x00000000000000;

int qpart( double dval, int &i ){
    int len( 0 );    
        
    dval -= floor( dval );
    if( MIN_DOUBLE == dval ) return len;    
    while( fabs( dval - floor( dval ) ) != MIN_DOUBLE ){
        dval *= 10;
        printf( "dval=%f\t_round(dval)=%f\n", dval, floor( dval ) );
        getch();
        len++;        
    }
    i = ( int )( floor( dval ) );
    return len;
}

int main( int argc, char* argv[] ){
    int    i( 0 );    
    
    qpart( 1.2221, i );
    printf( "i = %i\n", i );    
    return 0;
}

 
PM MAIL   Вверх
Earnest
Дата 22.5.2006, 16:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 5962
Регистрация: 17.6.2005
Где: Рязань

Репутация: 53
Всего: 183



Да не "не равно"! А "больше или равно"! 
Код

   while( fabs( dval - i ) >= MIN_DOUBLE )

А у тебя что получилось? Пока эта разница не равна MIN_DOUBLE цикл работает ...
А надо: пока разница ненулевая (т.е. больше эпсилон) ...

Да ты еще и MIN_DOUBLE нулем сделал... Что в лоб, что по лбу.
Надо, например: 
Код

const double MIN_DOUBLE = 1e-10;

И лучше константу использовать, чем макрос.
И не нужны никакие floor... У тебя нормальнгый алгоритм... Знание C вот... хромает ... 


--------------------
...
PM   Вверх
oper54
Дата 22.5.2006, 16:25 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 217
Регистрация: 13.5.2005

Репутация: 1
Всего: 1



Цитата

const double MIN_DOUBLE = 1e-10;

а что тут есть le? 
PM MAIL   Вверх
oper54
Дата 22.5.2006, 16:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 217
Регистрация: 13.5.2005

Репутация: 1
Всего: 1



а понял, торможу... 1e-10 
PM MAIL   Вверх
_hunter
Дата 22.5.2006, 16:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Участник Клуба
Сообщений: 8564
Регистрация: 24.6.2003
Где: Europe::Ukraine:: Kiev

Репутация: 16
Всего: 98



это не LE а 1(один)e
1*10 в -10-й степени 


--------------------
Tempora mutantur, et nos mutamur in illis...
PM ICQ   Вверх
oper54
Дата 22.5.2006, 16:47 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 217
Регистрация: 13.5.2005

Репутация: 1
Всего: 1



спасиб, теперь работает...
Код

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

const double MIN_DOUBLE        = 1e-10;

int qpart( double dval, int &i ){    
    int len( 0 );    
     
    dval -= ( int )( dval );    
    if( 0 == dval ) return len;    
    while( fabs( dval - floor( dval ) ) >= MIN_DOUBLE ){        
        dval *= 10;        
        len++;    
    }
    i = ( int )( dval );
    return len;    
}    

int main( int argc, char* argv[] ){    
    int    i;    
    qpart( 1.2133, i );    
    printf( "i = %i\n", i );    
    return 0;    
}

 
PM MAIL   Вверх
Earnest
Дата 22.5.2006, 17:02 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 5962
Регистрация: 17.6.2005
Где: Рязань

Репутация: 53
Всего: 183



Ну слава богу, поздравляю  smile 
Закрывай вопрос-то. 


--------------------
...
PM   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
Earnest Daevaorn

Добро пожаловать!

  • Черновик стандарта C++ (за октябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика(4.4мб).
  • Черновик стандарта C (за сентябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика (3.4мб).
  • Прежде чем задать вопрос, прочтите это и/или это!
  • Здесь хранится весь мировой запас ссылок на документы, связанные с C++ :)
  • Не брезгуйте пользоваться тегами [code=cpp][/code].
  • Пожалуйста, не просите написать за вас программы в этом разделе - для этого существует "Центр Помощи".
  • C++ FAQ

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.1175 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.