Здравствуйте, LaptevVV, Вы писали:
LVV>При присвоении к целому типу происходит ОТСЕЧЕНИЕ, поэтому перед присвоением надо сделать округление — вызвать функцию типа round (нодосуг сейчас самому искать в помощи) до второго знака после запятой. А потом уже можно присваивать целому.
Отсечение — это нахождение ближайшего целого снизу, функция double ceil(double) или просто оператор int().
Округление — это ceil(f+0.5).
Есть еще нахождение ближайшего целого сверху — double floor(double)
Если нужно округлить с точностью до третьего разряда, то пишем ceil(f*1000 + 0.5)*0.001
Здравствуйте, Кодт, Вы писали:
К>Отсечение — это нахождение ближайшего целого снизу, функция double ceil(double) или просто оператор int(). К>Округление — это ceil(f+0.5).
К>Есть еще нахождение ближайшего целого сверху — double floor(double)
Ай-я-яй! В действительности все не так, как на самом деле! А как раз наоборот!
Здравствуйте, Аноним, Вы писали:
А>не понял, а при чем тут округление?? в моем примере fVal выводится нормально, без округления! да и потом 8,40 можно округлить до 8, но никак не до 8,39... А>и почему тогда никакие другие значения fVal так хитро не округляются? почему только 8,40
А притом здесь округление, что в ЭВМ используется двоичное представление чисел.
Десятичное 8,4 = двоичное 1000,(0110) — периодичесая дробь; т. е. это число непредставимо в виде конечной двоичной дроби, и его приходится округлять до размера разрядной сетки.
Таким образом, на деле хранится что-то вроде 1000,011001100110011001100110011, и это округленное число может оказаться чуть больше или меньше исходного.
А>Мда... проблемма примерно понятно, а как с этим бороться???
А как ты борешься с тем, что 2/3 не представима в виде конечной десятичной дроби? Тебя это не сильно беспокоит? Почему же тогда надо беспокоиться о том, что некоторые числа не представимы в виде конечной двоичной дроби?
если в fVal поставить любое другое число, то все работает нормально.
например, если fVal = 8.30, то nVal = 830; только 8.40 приводит к такому странному эфекту.
толи я что-то не понимаю, толи это какое то число зарезервированное компилятором для своиз целей
подскожите, как с этим бороться?
А>выводит: fVal = 8.400000, nVal = 839 А>если в fVal поставить любое другое число, то все работает нормально. А>например, если fVal = 8.30, то nVal = 830; только 8.40 приводит к такому странному эфекту.
Да это просто округление при выводе. Посмотри на этот текст
А>>выводит: fVal = 8.400000, nVal = 839 А>>если в fVal поставить любое другое число, то все работает нормально. А>>например, если fVal = 8.30, то nVal = 830; только 8.40 приводит к такому странному эфекту. LVV>Да это просто округление при выводе. Посмотри на этот текст
LVV>
LVV>Понятно?
не понял, а при чем тут округление?? в моем примере fVal выводится нормально, без округления! да и потом 8,40 можно округлить до 8, но никак не до 8,39...
и почему тогда никакие другие значения fVal так хитро не округляются? почему только 8,40
Re[4]: магическое число??
От:
Аноним
Дата:
31.08.03 12:25
Оценка:
Здравствуйте, Аноним, Вы писали:
А>Здравствуйте, Аноним, Вы писали:
А>>не понял, а при чем тут округление?? в моем примере fVal выводится нормально, без округления! да и потом 8,40 можно округлить до 8, но никак не до 8,39... А>>и почему тогда никакие другие значения fVal так хитро не округляются? почему только 8,40
А>А притом здесь округление, что в ЭВМ используется двоичное представление чисел.
А>Десятичное 8,4 = двоичное 1000,(0110) — периодичесая дробь; т. е. это число непредставимо в виде конечной двоичной дроби, и его приходится округлять до размера разрядной сетки.
А>Таким образом, на деле хранится что-то вроде 1000,011001100110011001100110011, и это округленное число может оказаться чуть больше или меньше исходного.
Мда... проблемма примерно понятно, а как с этим бороться???
Re[5]: магическое число??
От:
Аноним
Дата:
31.08.03 12:28
Оценка:
Здравствуйте, Аноним, Вы писали:
А>Мда... проблемма примерно понятно, а как с этим бороться???
Проблемы нет. Просто типы данных нужно выбирать по задаче, либо уметь вручную округлять.
Здравствуйте, Аноним, Вы писали:
А>Здравствуйте, Аноним, Вы писали:
А>>Мда... проблемма примерно понятно, а как с этим бороться???
А>Проблемы нет. Просто типы данных нужно выбирать по задаче, либо уметь вручную округлять.
он имеет ввиду, что работать скажем не с float а с double (уже практически стандарт, float забыл когда в последний раз видел)
или же вообще с longlong... только считать что у него в середине запятая..
Здравствуйте, vvaizh, Вы писали:
А>>Проблемы нет. Просто типы данных нужно выбирать по задаче, либо уметь вручную округлять.
V>он имеет ввиду, что работать скажем не с float а с double (уже практически стандарт, float забыл когда в последний раз видел)
double не поможет. Сетка там шире, но и она не бесконечна, и проблемы периодичесих дробей не решит.
V>или же вообще с longlong... только считать что у него в середине запятая..
Если речь идет о хранении денежных величин, то наиболее разумный подход — использовать тип данных с фиксированной точкой, сиречь масштабированные целые.
Например, при использовании типа long long int в Си (__int64 в MSVC++) с масштабным множителем 10000 можно представить любую мыслимую денежную сумму с точностью до 1/10000 руб. = 1/100 коп. без потери точности.
Re[8]: магическое число??
От:
Аноним
Дата:
31.08.03 14:46
Оценка:
Здравствуйте, Аноним, Вы писали:
А>Здравствуйте, vvaizh, Вы писали:
А>>>Проблемы нет. Просто типы данных нужно выбирать по задаче, либо уметь вручную округлять.
V>>он имеет ввиду, что работать скажем не с float а с double (уже практически стандарт, float забыл когда в последний раз видел)
А>double не поможет. Сетка там шире, но и она не бесконечна, и проблемы периодичесих дробей не решит.
V>>или же вообще с longlong... только считать что у него в середине запятая..
А>Если речь идет о хранении денежных величин, то наиболее разумный подход — использовать тип данных с фиксированной точкой, сиречь масштабированные целые.
А>Например, при использовании типа long long int в Си (__int64 в MSVC++) с масштабным множителем 10000 можно представить любую мыслимую денежную сумму с точностью до 1/10000 руб. = 1/100 коп. без потери точности.
На самом деле задача тривиальна... есть контрол, в котором пользовотель вводит стоимость некой услуги, это надо сохранить в базе (типа справочник), так вот когда пользовотель вводит 8,40, то в базе сохраняется 8,39, и еслественно его (пользовотеля ) такое абсолютно не устраивает.
то что пользовотель ввел преобразуется простейшим способом:
берем из Edit'а значение в char, а потом fVal = atof(char); при этом fVal = 8,40.
далее, в базу кладу только целые числа, для этого перед тем как положить умножаю fVal на 100, ну и естественно после того, как забираю делю на 100,... работу с базой поменять не могу, так как это творчество заказчика, и мне нужно все вписать в его базу
Здравствуйте, Аноним, Вы писали:
А>На самом деле задача тривиальна... есть контрол, в котором пользовотель вводит стоимость некой услуги, это надо сохранить в базе (типа справочник), так вот когда пользовотель вводит 8,40, то в базе сохраняется 8,39, и еслественно его (пользовотеля ) такое абсолютно не устраивает. А>то что пользовотель ввел преобразуется простейшим способом: А>берем из Edit'а значение в char, а потом fVal = atof(char); при этом fVal = 8,40. А>далее, в базу кладу только целые числа, для этого перед тем как положить умножаю fVal на 100, ну и естественно после того, как забираю делю на 100,... работу с базой поменять не могу, так как это творчество заказчика, и мне нужно все вписать в его базу
Еще раз: fVal = atof(char); при этом fVal = 8,40 — это только "на бумаге", то есть на экране. А внутри — как тут уже писали, и я приводил — 839999...
При присвоении к целому типу происходит ОТСЕЧЕНИЕ, поэтому перед присвоением надо сделать округление — вызвать функцию типа round (нодосуг сейчас самому искать в помощи) до второго знака после запятой. А потом уже можно присваивать целому.
Хочешь быть счастливым — будь им!
Без булдырабыз!!!
А>Если речь идет о хранении денежных величин, то наиболее разумный подход — использовать тип данных с фиксированной точкой, сиречь масштабированные целые.
А>Например, при использовании типа long long int в Си (__int64 в MSVC++) с масштабным множителем 10000 можно представить любую мыслимую денежную сумму с точностью до 1/10000 руб. = 1/100 коп. без потери точности.
если речь идет о денежных величинах, то хранить надо все значения в минимальной денежной единице используемой валюты (копейки, центы, гроши)
Веру-ю-у! В авиацию, в научную революци-ю-у, в механизацию сельского хозяйства, в космос и невесомость! Веру-ю-у! Ибо это объективно-о! (Шукшин)