Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > C/C++ программирование > Общие вопросы C/C++
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 16.08.2012, 18:43   #1
Theseus
Пользователь
 
Аватар для Theseus
 
Регистрация: 11.02.2009
Сообщений: 29
По умолчанию Проблема с преобразоварнием double в int

Доброго времени суток. Есть функция которая вычисляет длину строки (в символах) которая выводится в консоль при отправки туда чисел с плавающей точкой, но вот проблема: при вычислении длины дробной части функция работает неправильно! Принцип по которому она должна работать следующий:
  1. умножаем дробную часть на 10
  2. отнимаем от полученого числа его же приведённое к типу long int
Всё это работает в цикле, условием завершения которого является равенство дробной части нулю. По количеству итераций определяется длина строки.
Ну и в конце если дробная часть не равна нулю прибавляем единицу чтобы учесть десятичную точку (как не странно это тоже символ ).
Только вот в шаге 2 происходят какие-то проблемы с static_cast<long int>(fractional_part), я ввожу в программу число 0.13 и больше ничего, но как видно на скриншоте программа при отнимании от трёх три получает не 0, а 4.44089e-016. Откуда берутся эти мелкие остатки непонятно может кто подскажет что-то дельное?
Ах да, забыл добавить функция debug::v(type , const char *), просто выводит переменную типа type, под именем которое предаётся с помощью второго аргумента const char *.

Вот исходный код:

Код:
#include <iostream>
#include "debug.h"
int number_length(const long double & number)
{
    //coutnter for integer part
    long int int_part=static_cast<long int>(number);
    int length_int_part(0); while(int_part)
    {
        int_part/=10;
        length_int_part++;
    }
    if(length_int_part==0) length_int_part++;
    //counter for fractional part
    long double fractional_part=number-static_cast<long int>(number);
    debug::v(fractional_part, "fractional_part(give to cycle)");
    int length_fract_part(0); if(fractional_part<1) while(fractional_part)
    {
        fractional_part*=10;
        debug::v(fractional_part, "fractional_part(after *10)");
        long int after_cast=static_cast<long int>(fractional_part);
        debug::v(after_cast, "after_cast(after convrsion to long int)");
        fractional_part-=after_cast;
        debug::v(fractional_part, "fractional_part(after -int part)");
        length_fract_part++;
    }
    else throw "number_length() > 10";
    if(length_fract_part) length_fract_part++;
    debug::v(length_int_part, "length_int_part");
    debug::v(length_fract_part, "length_fract_part");
    return length_int_part+length_fract_part;
}
int main()
{
    double i;
    while(std::cin>>i)
    {
        try
        {
            std::cout<<"number_length() = "<<number_length(i)<<std::endl;
        }
        catch(const char * error_message)
        {
            std::cout<<error_message<<std::endl;
            continue;
        }
    }
}
А вот что она выводит:


Последний раз редактировалось Theseus; 16.08.2012 в 18:51.
Theseus вне форума Ответить с цитированием
Старый 16.08.2012, 19:02   #2
Гром
Старожил
 
Аватар для Гром
 
Регистрация: 21.03.2009
Сообщений: 2,193
По умолчанию

Чтобы не повторяться, смотрите ответ #3 в этой теме.
Вместо проверки на равенство нулю (что для чисел с плавающей точкой, как и в вашем случае, может оказаться неверным), сравнивайте, меньше ли число некоего заранее заданного малого delta. Посмотрите в сторону std::numeric_limits<double>::epsilo n(), возможно, это то, что вам нужно.

И, да, генерировать в качестве исключения строку - не самый лучший вариант. Лучше создайте специальный класс исключения (например, наследник std::runtime_error).
Простые и красивые программы - коды программ + учебник C++
Создание игры - взгляд изнутри - сайт проекта
Тема на форуме, посвященная ему же
Гром вне форума Ответить с цитированием
Старый 17.08.2012, 15:16   #3
Theseus
Пользователь
 
Аватар для Theseus
 
Регистрация: 11.02.2009
Сообщений: 29
По умолчанию

Спасибо за ответ!
Theseus вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
проблема с short и double guest45833 Visual C++ 3 23.02.2012 14:40
функция float average(int arrray[],int from,int to) yuliyayuliya Помощь студентам 0 25.04.2011 21:55
int mass to double Alex_sim Общие вопросы .NET 9 08.05.2010 16:25
округливание в C#( double to int) Natok Помощь студентам 1 25.05.2009 22:58
преобразование int в double Си++ t1empo Помощь студентам 11 27.04.2009 19:31