получение дробной части от double и modf
От: needDrivers  
Дата: 11.11.09 09:10
Оценка:
Здравствуйте!

Понадобилось отделить дробную часть от числа (копейки отделить от рублей).
Подскажите, что я делаю не так?

На выходе надо получить два целых числа — рубли и копейки.
    char tmp[1024];
    double zz;
    double yy;
    int i;

        // извлекаю в переменную yy дробную часть от 3.03, умножаю её на 100 и кладу в yy
    yy = modf(3.03, &zz) * 100;            // здесь yy = 3
    sprintf(tmp, "%f", yy);                // tmp = "3.000000"
    MessageBox(NULL, tmp, "modf", MB_OK);

        // извлекаю из yy целую часть в zz
    modf(yy, &zz);                        // а вот здесь начинается мистика - zz почему-то равен 2 ???
    sprintf(tmp, "3 = %f", zz);
    MessageBox(NULL, tmp, "modf", MB_OK);

    i = (int) yy;
    sprintf(tmp, "3 = %d", kop);
    MessageBox(NULL, tmp, "modf", MB_OK);
Re: получение дробной части от double и modf
От: MasterZiv СССР  
Дата: 11.11.09 09:27
Оценка:
needDrivers wrote:

> Понадобилось отделить дробную часть от числа (копейки отделить от рублей).

> Подскажите, что я делаю не так?

Ты неправильно используешь тип DOUBLE. В переменных такого типа
воообще нет недробной части. Всё число -- дробная часть.
Так что что от чего ты собираешся отделять -- вообще непонятно.
Posted via RSDN NNTP Server 2.1 beta
Re[2]: получение дробной части от double и modf
От: needDrivers  
Дата: 11.11.09 09:33
Оценка:
Хорошо, как сделать правильно?
Есть число 3.03 из него надо получить 3 рубля 3 копейки.
Re[3]: получение дробной части от double и modf
От: Кодт Россия  
Дата: 11.11.09 11:28
Оценка:
Здравствуйте, needDrivers, Вы писали:

D>Хорошо, как сделать правильно?

D>Есть число 3.03 из него надо получить 3 рубля 3 копейки.
К сожалению, нет числа 3.03. Оно непредставимо в двоичной плавающей форме, там в действительности что-то вида 3.029999999... (с ошибкой в 14 знаке).

Выходов три:
— Пользоваться double для рублей, но постоянно принуждать к округлению до 3 знака после запятой
Пользоваться int для копеек
— Написать собственный тип currency, реализующий десятичную, а не двоичную арифметику. Вот не помню, поддерживает ли интеловский FPU десятичную плавающую точку по IEEE, или нет. Если да, то можно будет привлечь ассемблер. Если нет — то всё ручками.
... << RSDN@Home 1.2.0 alpha 4 rev. 1237>>
Перекуём баги на фичи!
Re[3]: получение дробной части от double и modf
От: Vain Россия google.ru
Дата: 11.11.09 11:33
Оценка:
Здравствуйте, needDrivers, Вы писали:

D>Хорошо, как сделать правильно?

D>Есть число 3.03 из него надо получить 3 рубля 3 копейки.
Надо понять для начала, что нет такого числа. Это десятичное представление двоичного числа, т.е. аппроксимация двоичного значения десятичным. Т.е. если число 3.03 (сумма) и точно представимо, это не значит, что числа 3.0 и 0.03 точно представимы.
[In theory there is no difference between theory and practice. In
practice there is.]
[Даю очевидные ответы на риторические вопросы]
Re[4]: получение дробной части от double и modf
От: needDrivers  
Дата: 11.11.09 11:50
Оценка:
Мне нужно преобразовать double в "число прописью".
Нашёл функцию, которая преобразовывает целое в пропись.
Я решил разбить double на целую и дробную часть, но в копейках появляется неточность.
3 копейки превращаются в 2
5 копеек в 4 и т.п.

Наверняка кто-нибудь делал подобное. Как правильно реализовать данную функцию?
Re[5]: получение дробной части от double и modf
От: Vain Россия google.ru
Дата: 11.11.09 12:35
Оценка:
Здравствуйте, needDrivers, Вы писали:

D>Мне нужно преобразовать double в "число прописью".

D>Нашёл функцию, которая преобразовывает целое в пропись.
D>Я решил разбить double на целую и дробную часть, но в копейках появляется неточность.
D>3 копейки превращаются в 2
D>5 копеек в 4 и т.п.
D>Наверняка кто-нибудь делал подобное. Как правильно реализовать данную функцию?
Тебе не число надо реализовывать, а изначально считать в десятичной системе, если хочешь десятичную точность. Посмотри библиотеку GMP
[In theory there is no difference between theory and practice. In
practice there is.]
[Даю очевидные ответы на риторические вопросы]
Re[6]: получение дробной части от double и modf
От: needDrivers  
Дата: 11.11.09 13:13
Оценка:
V>Тебе не число надо реализовывать, а изначально считать в десятичной системе, если хочешь десятичную точность. Посмотри библиотеку GMP

Как понять: считать в десятичной системе? Хранить отдельно целую и отдельно дробную части числа?
Я ничего не рассчитываю. Есть БД в которой хранятся суммы в формате double. Надо в печатную форму выводить эти суммы в виде чисел и прописью.
12000.03 (Двенадцать тысяч рублей 3 копейки)

Спасибо за ссылку, посмотрю.
Re[7]: получение дробной части от double и modf
От: McQwerty Россия  
Дата: 11.11.09 13:29
Оценка: 1 (1)
Здравствуйте, needDrivers, Вы писали:

D>Как понять: считать в десятичной системе? Хранить отдельно целую и отдельно дробную части числа?

D>Я ничего не рассчитываю. Есть БД в которой хранятся суммы в формате double. Надо в печатную форму выводить эти суммы в виде чисел и прописью.
D>12000.03 (Двенадцать тысяч рублей 3 копейки)

Тогда, типа, так:

// s - сумма (double)
// r - рубли (целое)
// k - копейки (целое)
// 0.005 - полкопейки на всяко-разно вокруг double
const int r = (s + 0.005);
const int k = (s - r + 0.005) * 100;
Re[8]: получение дробной части от double и modf
От: needDrivers  
Дата: 12.11.09 07:51
Оценка:
Думал про такую же реализацию, но казалось, что это будет не правильно.
Спасибо! Твой метод работает.
Re: получение дробной части от double и modf
От: Alexander G Украина  
Дата: 12.11.09 10:57
Оценка:
Здравствуйте, needDrivers, Вы писали:

D>Здравствуйте!


D>Понадобилось отделить дробную часть от числа (копейки отделить от рублей).

D>Подскажите, что я делаю не так?

Немного не по теме, а разве для денег используют числа с плавающей точкой?
Кое-где, в частности в Delphi, есть тип currency с фиксированной точкой.
В С, я думал, следует использовать long long.
Русский военный корабль идёт ко дну!
Re[4]: получение дробной части от double и modf
От: MasterZiv СССР  
Дата: 13.11.09 14:15
Оценка:
Кодт wrote:

> Выходов три:

> — Пользоваться double для рублей, но постоянно принуждать к округлению
> до 3 знака после запятой
> — *Пользоваться int для копеек*
> — Написать собственный тип currency, реализующий десятичную, а не
> двоичную арифметику.

Есть третий путь. Использовать один из готовых таких классов.
Или библиотек.

Вот не помню, поддерживает ли интеловский FPU
> десятичную плавающую точку по IEEE, или нет. Если да, то можно будет
> привлечь ассемблер. Если нет — то всё ручками.

Там есть поддержка BCD, не в FPU, а в основном процессоре. Хотя
на сколько я понимаю уже давно всё на одном кристалле.
Posted via RSDN NNTP Server 2.1 beta
Re[7]: получение дробной части от double и modf
От: MasterZiv СССР  
Дата: 13.11.09 14:16
Оценка:
needDrivers wrote:

> Я ничего не рассчитываю. Есть БД в которой хранятся суммы в формате

> double.

Это очень плохо. Значит, вам придётся переделывать и БД тоже
Проверь, может быть в БД всё же какой-то NUMERIC, а ты только
на клиенте его в виде double получаешь.
Posted via RSDN NNTP Server 2.1 beta
Re[2]: получение дробной части от double и modf
От: MasterZiv СССР  
Дата: 13.11.09 14:20
Оценка:
Alexander G wrote:

> Немного не по теме, а разве для денег используют числа с плавающей точкой?


Ну как, если вменяемые разработчкики, и если это не
статистические расчёты , то не используется.

(для статистики как раз лучше (ну, возможно) плавующуу точку использовать,
потому как средняя зарплата в 20000 рублей 25.6 копеек --
это нормально. А вот выданная зарплата за февраль Иванову 20000 рублей 25.6
копеек -- это нонсенс.)
Posted via RSDN NNTP Server 2.1 beta
Re: получение дробной части от double и modf
От: Sni4ok  
Дата: 13.11.09 19:04
Оценка: -1
Здравствуйте, needDrivers, Вы писали:

на самом деле вам тут насоветовавали кучу всякой туфты, double отлично может хранить цену, многие торговые терминалы так и делают,
что касается вашего кода, то 2 раза вызывать modf — смысла нет, одного вполне достаточно

D>
D>    char tmp[1024];
D>    double zz;
D>    double yy;
D>    int i;

        yy = modf(3.03, &zz);
        i = int(100 * (yy + DBL_EPSILON)) // ну или std::numeric_limits<double>::epsilon() вместо DBL_EPSILON если от си тошнит
D>
Re[2]: получение дробной части от double и modf
От: needDrivers  
Дата: 16.11.09 06:17
Оценка:
В БД действительно используется double, потому что таблицу создавал я.
Double использовал от недостатка знаний и о типе данных с фиксированной точкой только догадывался.
Спасибо большое за советы, в дальнейшем буду переходить на фиксированную точку.

Не могли бы дать хорошие примеры или советы по работе с фиксированной точкой?
Какой тип данных использовать для хранения чисел с фиксированной точкой __int64?
Re[3]: получение дробной части от double и modf
От: MasterZiv СССР  
Дата: 16.11.09 06:46
Оценка:
needDrivers wrote:

> Не могли бы дать хорошие примеры или советы по работе с фиксированной

> точкой?

Ну, какие тут могут быть советы ...
Используй -- вот главный совет.
Отличай случаи, когда надо использовать, от случаев, когда не надо
(редко, и в основном -- статистические расчёты). Ну т.е. надо прежде
всего решить, какой тип арифметики использовать: точную или плавающую.
Если точная арифметика -- надо чётко понимать, как при вычислении
выражений округлять результаты, и в каком месте. Постановщики задач
часто об этом не думают, надо из них это вытрясать.
Если не будешь округлять, можно получить переполнение достаточно быстро.

Правило вычисления точности результата:

N1.M1 * N2.M2 = N1+N2.M1+M2 (если не ошибаюсь),
где
N1, N2 -- кол-во цифр до дес. точки,
M1, M2 -- кол-во цифр после дес. точки.

> Какой тип данных использовать для хранения чисел с фиксированной точкой


На клиенте СУБД нужно использовать либо типы данных, предоставляемые
клиентской библиотекой СУБД, если такие есть, либо какие-то универсальные
типы данных, предоставляемые языком, или библиотекой, или ещё чем-то
(как напр. currency в VB). Ну, или использовать библиотеки длинных
точных чисел, типа Gnu MP.
Posted via RSDN NNTP Server 2.1 beta
Re[8]: получение дробной части от double и modf
От: trophim Россия  
Дата: 28.11.09 12:07
Оценка:
Надеюсь, это не БД в налоговой...
... << RSDN@Home 1.2.0 alpha 4 rev. 1111>>
Let it be! — Давайте есть пчелу!
Re: получение дробной части от double и modf
От: yatagarasu Беларусь  
Дата: 28.11.09 12:21
Оценка:
Здравствуйте, needDrivers, Вы писали:

D>Здравствуйте!


D>Понадобилось отделить дробную часть от числа (копейки отделить от рублей).

D>Подскажите, что я делаю не так?
Никогда, никогда, никогда нельзя использовать типы с плавающей точкой для хранения величин за точность которых можно получить по еб@лу.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.