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

Поиск:

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


Бывалый
*


Профиль
Группа: Участник
Сообщений: 180
Регистрация: 18.6.2009
Где: Южно-Сахалинск

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



Привет всем. как преобразовать число из типа double в тип int.

Windows Vista SP2, MSVS 2008 SP1


Вот такой код не работает на моем компе. если делать округление функцией ceil то все нормально переводится. 

Код

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

int _tmain()
{
    double p = 0.9888;
    double sl = 0.9885;
    double st = pow((double)10,4);
    double a = (p-sl)*st;
    
    //int c = ceil(a);
    int b = a;
    printf("%lf,%d\n",a,b);
    return 0;
}


Вопрос наверно такой: как определить когда надо использовать округление а когда не надо?

Это сообщение отредактировал(а) jimbo - 24.2.2011, 14:47
--------------------
Я не играю в шахматы - в шахматах я борюсь. А.А.Алехин
PM MAIL WWW   Вверх
Modul
Дата 24.2.2011, 15:05 (ссылка)    | (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


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

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



А Вы сами напишите, что думаете. А сообщество подскажет дальше...
--------------------
I'll be back !
PM MAIL   Вверх
mes
Дата 24.2.2011, 15:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


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

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



Цитата(jimbo @  24.2.2011,  13:45 Найти цитируемый пост)
Вот такой код не работает на моем компе. 

а как именно не работает - это, наверно военная тайна..

Цитата(jimbo @  24.2.2011,  13:45 Найти цитируемый пост)
как определить когда надо использовать округление а когда не надо?

зависит от задачи, которую Вы забыли сформулировать.. 


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


Бывалый
*


Профиль
Группа: Участник
Сообщений: 180
Регистрация: 18.6.2009
Где: Южно-Сахалинск

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



Цитата(mes @ 24.2.2011,  15:56)
Цитата(jimbo @  24.2.2011,  13:45 Найти цитируемый пост)
Вот такой код не работает на моем компе. 

а как именно не работает - это, наверно военная тайна..

Ну почему же? не тайна.

я запускал этот код на своем компе и на соседнем, там стоит хр.

всегда результат был таким:
3.000000,2


Математическое выражение (0.9888 - 0.9885) * 10^4 =  0.0003 * 10000 = 3

в типе double это число получается 2,9999999999999 
с приведением к типу int получается 2. 
Ну не логично же, нет?

Вопрос из сабжа. как преобразовать тип double в int "по-человечески" ?
--------------------
Я не играю в шахматы - в шахматах я борюсь. А.А.Алехин
PM MAIL WWW   Вверх
borisbn
Дата 24.2.2011, 16:23 (ссылка)    | (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 4875
Регистрация: 6.2.2010
Где: Ростов-на-Дону

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



jimbo, запусти вот это
Код

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

int main()
{
    double two_and_1 = 2.1;
    double two_and_9 = 2.9; 
    printf( "two_and_1 = %lf\n", two_and_1 );
    printf( "two_and_9 = %lf\n", two_and_9 );
    int i_two_and_1 = (int)two_and_1;
    int i_two_and_9 = (int)two_and_9; 
    printf( "i_two_and_1 = %d\n", i_two_and_1 );
    printf( "i_two_and_9 = %d\n", i_two_and_9 );
    int ceil_two_and_1 = ceil( two_and_1 );
    int ceil_two_and_9 = ceil( two_and_9 ); 
    printf( "ceil_two_and_1 = %d\n", ceil_two_and_1 );
    printf( "ceil_two_and_9 = %d\n", ceil_two_and_9 );

    int round_two_and_1 = (int)( two_and_1 + 0.5 );
    int round_two_and_9 = (int)( two_and_9 + 0.5 );
    printf( "round_two_and_1 = %d\n", round_two_and_1 );
    printf( "round_two_and_9 = %d\n", round_two_and_9 );

    return 0;
}

и, думаю, будет всё понятно

Это сообщение отредактировал(а) borisbn - 24.2.2011, 16:29


--------------------
Женщины отличаются от программистов тем, что у них чары состоят из стрингов
PM MAIL Jabber   Вверх
mes
Дата 24.2.2011, 16:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


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

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



Цитата(jimbo @  24.2.2011,  15:06 Найти цитируемый пост)
как преобразовать тип double в int "по-человечески" ? 

это не преобразование, а округление.. стандартной функции round нет.. гугль поможет найти библиотечку, где такая есть..
если хотите самостоятельно реализовать, то правила простые :
Цитата

Roundings to nearest
Round to nearest, ties to even – rounds to the nearest value; if the number falls midway it is rounded to the nearest value with an even (zero) least significant bit, which occurs 50% of the time; this is the default algorithm for binary floating-point and the recommended default for decimal
Round to nearest, ties away from zero – rounds to the nearest value; if the number falls midway it is rounded to the nearest value above (for positive numbers) or below (for negative numbers)

http://en.wikipedia.org/wiki/IEEE_754-2008


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


Бывалый
*


Профиль
Группа: Участник
Сообщений: 180
Регистрация: 18.6.2009
Где: Южно-Сахалинск

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



запустил. 
на все вопросы он мне не ответил. 

Тут одинаковый код только цифры разные. У меня на компе ii = 3 а с = 2. У вас не так? Запустите и посмотрите. ВСЕГДА должно быть 3 - это чисто математически верно, нет других вариантов. Компьютер же считает иначе. я так полагаю из-за хранения типа double, получается неточность, в итоге инт у нас равен 2. Потом по коду я перевожу дабл в строку и строку в инт. результат ошеломляющий и блин верный.  дубль два - как по-человечески перевести тип дабл в инт. Есть ли возможность задать типу дабл точность до 10 знаков после запятой или как-то избегать ответов "no" в коде. Считайте что числа `p` и `sl` всегда разные.

Код

        double t = 0.0005;
    double k = 0.0002;
    double dif = t-k;

    double d_dif = dif * 10000;

    int ii = (int)d_dif;
    printf("%lf,%d\n",d_dif,ii);

    double p = 0.9888;
    double sl = 0.9885;
    double a = (p-sl)*10000;    
    
    int c = a;        
    printf("%lf,%d\n",a,c);

    if(a >= 3)
    {
        printf("yes\n");
    }
    else printf("no\n");

char ss[32];
    sprintf_s(ss,31,"%lf",a);
    int dd = atoi(ss);
    printf("%d,%lf\n",dd,a);

    if(dd >= 3)
    {
        printf("yes\n");
    }
    else printf("no\n");

--------------------
Я не играю в шахматы - в шахматах я борюсь. А.А.Алехин
PM MAIL WWW   Вверх
mes
Дата 24.2.2011, 17:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


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

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



Цитата(jimbo @  24.2.2011,  15:51 Найти цитируемый пост)
Компьютер же считает иначе. я так полагаю из-за хранения типа double, получается неточность, в итоге инт у нас равен 2.

из за способа округления.. стандартных только два : 
Цитата(floor)

Returns the largest integral value that is not greater than x.

http://www.cplusplus.com/reference/clibrary/cmath/floor/

Цитата(ceil)

Returns the smallest integral value that is not less than x.

http://www.cplusplus.com/reference/clibrary/cmath/ceil/

оба они Вам не подходят.. 

Цитата

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



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


Бывалый
*


Профиль
Группа: Участник
Сообщений: 180
Регистрация: 18.6.2009
Где: Южно-Сахалинск

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



я реализовал через строки. Но боже мой, какой тупизм!!
--------------------
Я не играю в шахматы - в шахматах я борюсь. А.А.Алехин
PM MAIL WWW   Вверх
borisbn
Дата 24.2.2011, 18:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 4875
Регистрация: 6.2.2010
Где: Ростов-на-Дону

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



Цитата(jimbo @  24.2.2011,  17:55 Найти цитируемый пост)
я реализовал через строки. Но боже мой, какой тупизм!!

действительно, не лучшее решение

Цитата(jimbo @  24.2.2011,  16:51 Найти цитируемый пост)
в итоге инт у нас равен 2

точнее не int, а результат Вашего округления (читай отбрасывания дробной части).
если преобразовывать так
Код

int ii = (int)(double_value + 0.5);

то будет правильное округление

и еще, написав, double p = 0.9888; Вы не получите десятичное число 0.9888 в переменной p. отсюда, скорее всего, и вопросы.

jimbo, объясните суть задачи, и Вам, скорее всего, помогут её решить...

Это сообщение отредактировал(а) borisbn - 24.2.2011, 18:08


--------------------
Женщины отличаются от программистов тем, что у них чары состоят из стрингов
PM MAIL Jabber   Вверх
mes
Дата 24.2.2011, 18:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


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

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



Цитата(borisbn @  24.2.2011,  17:06 Найти цитируемый пост)
то будет правильное округление

для отрицательных тоже ?  smile

Добавлено через 2 минуты и 10 секунд
Цитата(jimbo @  24.2.2011,  16:55 Найти цитируемый пост)
Но боже мой, какой тупизм!! 

имхо, Вам проще всего будет реализовать на основе modf

Добавлено через 3 минуты и 6 секунд
или доработать приведенное borisbn..


--------------------
PM MAIL WWW   Вверх
jimbo
Дата 24.2.2011, 18:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 180
Регистрация: 18.6.2009
Где: Южно-Сахалинск

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



Задача сводится к преобразованию числа типа double к числу типа int. Причем не так как делает это компилятор (отбрасыванием дробной части) а математически. Разряд максимальный после запятой  - 10. То есть не надо супер приближений

Есть объект у которого есть метрика value. Она вещественная. Есть меняющийся стандарт. у него также есть метрика st_value. Есть минимальное отклонение st. Есть порог чувствительности level.

В течение времени можно создать много много объектов и у каждого будет своя value. Когда у какого-либо объекта метрика приближается к текущему стандату ближе чем порог чувствительности level необходимо обработать данные. 

Теперь смотрим. есть объект с value 0.9888. Текущий стандарт 0.9885. Порог чувствительности 3 минимальных отклонения. Минимальное отклонение 0.0001 (зачастую является степенью 10). Мне надо обработать данные судя по математическим числам, программа же моя не реагирует, потому что 2 не больше 3.

Код

if( (0,9888 - 0,9885 ) * 10^4 >= 3 ) 



Вот и получается что
Код


double result = (this->GetValue() - st_obj->GetValue())*pow(10.0,st_obj->Get10Dgr());
            char bs[64];
            sprintf_s(bs,63,"%lf",result);
            int levels = atoi(bs);
            if( levels >=st_obj->GetLevel()) Process()


Добавлено через 11 минут и 3 секунды
Цитата(mes @ 24.2.2011,  18:11)
Добавлено @ 18:13
Цитата(jimbo @  24.2.2011,  16:55 Найти цитируемый пост)
Но боже мой, какой тупизм!! 

имхо, Вам проще всего будет реализовать на основе modf

Или я не понял как пользоваться Modf или вот

Код


double a = (0.9888-0.9885)*10000;
double part;
double bbc = modf(a,&part);

out:
a = 2.99999
part = 2.00000
bbc = 0.99999

--------------------
Я не играю в шахматы - в шахматах я борюсь. А.А.Алехин
PM MAIL WWW   Вверх
mes
Дата 24.2.2011, 19:50 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


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

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



Цитата(jimbo @  24.2.2011,  17:28 Найти цитируемый пост)
или вот

теперь анализируйте дробную часть, и четность целой части (необязательно) и на основе это возвращайте правильно округленное значение..

Добавлено через 3 минуты и 48 секунд
Цитата(jimbo @  24.2.2011,  17:28 Найти цитируемый пост)
, потому что 2 не больше 3

вместо 3 (целое) используйте 3.0 или просто 3. (с точкой) и не надо будет округлять..





--------------------
PM MAIL WWW   Вверх
borisbn
Дата 24.2.2011, 22:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 4875
Регистрация: 6.2.2010
Где: Ростов-на-Дону

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



Цитата(mes @  24.2.2011,  18:11 Найти цитируемый пост)
для отрицательных тоже ?

быстрее (ответить в форум) - не значит правильнее smile smile smile
Код

int myRound( double d ) {
  int sign = (d >=0) : 1 : -1;
  return (int)(d + sign * 0.5);
}

jimbo, IMHO так должно работать 
Код

  double result = (this->GetValue() - st_obj->GetValue())*pow(10.0,st_obj->Get10Dgr());
  int levels = myRound( result );
  if( levels >=st_obj->GetLevel()) Process()


Это сообщение отредактировал(а) borisbn - 24.2.2011, 22:18


--------------------
Женщины отличаются от программистов тем, что у них чары состоят из стрингов
PM MAIL Jabber   Вверх
xvr
Дата 25.2.2011, 13:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

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



Цитата(jimbo @  24.2.2011,  18:28 Найти цитируемый пост)
Вот и получается что
Код

double result = (this->GetValue() - st_obj->GetValue())*pow(10.0,st_obj->Get10Dgr());
            char bs[64];
            sprintf_s(bs,63,"%lf",result);
            int levels = atoi(bs);
            if( levels >=st_obj->GetLevel()) Process()
А преобразовывать именно double в int для сравнения (а не наоборот) религия требует?  smile 
Код

double result = (this->GetValue() - st_obj->GetValue())*pow(10.0,st_obj->Get10Dgr());
            if( result >=st_obj->GetLevel()) Process()


PM MAIL   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
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.1512 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


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

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