магическое число??
От: Аноним  
Дата: 30.08.03 10:53
Оценка:
Может кто подскажет, что тут не так?



int main(int argc, char* argv[])
{
  float fVal = 8.40;
  int nVal = fVal*100;
  printf("Hello World!\n fVal = %f, nVal = %i", fVal, nVal);
  return 0;
}


выводит: fVal = 8.400000, nVal = 839

если в fVal поставить любое другое число, то все работает нормально.
например, если fVal = 8.30, то nVal = 830; только 8.40 приводит к такому странному эфекту.

толи я что-то не понимаю, толи это какое то число зарезервированное компилятором для своиз целей
подскожите, как с этим бороться?
Re: магическое число??
От: LaptevVV Россия  
Дата: 30.08.03 11:13
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Может кто подскажет, что тут не так?


А>
А>int main(int argc, char* argv[])
А>{
А>  float fVal = 8.40;
А>  int nVal = fVal*100;
А>  printf("Hello World!\n fVal = %f, nVal = %i", fVal, nVal);
А>  return 0;
А>}
А>


А>выводит: fVal = 8.400000, nVal = 839

А>если в fVal поставить любое другое число, то все работает нормально.
А>например, если fVal = 8.30, то nVal = 830; только 8.40 приводит к такому странному эфекту.
Да это просто округление при выводе. Посмотри на этот текст

int main(int argc, char* argv[])
{
  float fVal = 8.40;
  int nVal = fVal*10000000;
  printf("fVal = %10.8f, nVal = %i\n", fVal, nVal);
  cout << fVal << endl;
  getch();
  return 0;
}


Выводит
fVal = 8.39999962, nVal = 83999996
8.4

Понятно?
Хочешь быть счастливым — будь им!
Без булдырабыз!!!
Re[2]: магическое число??
От: Аноним  
Дата: 31.08.03 10:08
Оценка:
Здравствуйте, LaptevVV, Вы писали:

LVV>Здравствуйте, Аноним, Вы писали:


А>>Может кто подскажет, что тут не так?


А>>
А>>int main(int argc, char* argv[])
А>>{
А>>  float fVal = 8.40;
А>>  int nVal = fVal*100;
А>>  printf("Hello World!\n fVal = %f, nVal = %i", fVal, nVal);
А>>  return 0;
А>>}
А>>


А>>выводит: fVal = 8.400000, nVal = 839

А>>если в fVal поставить любое другое число, то все работает нормально.
А>>например, если fVal = 8.30, то nVal = 830; только 8.40 приводит к такому странному эфекту.
LVV>Да это просто округление при выводе. Посмотри на этот текст

LVV>
LVV>int main(int argc, char* argv[])
LVV>{
LVV>  float fVal = 8.40;
LVV>  int nVal = fVal*10000000;
LVV>  printf("fVal = %10.8f, nVal = %i\n", fVal, nVal);
LVV>  cout << fVal << endl;
LVV>  getch();
LVV>  return 0;
LVV>}
LVV>


LVV>Выводит

LVV>
LVV>fVal = 8.39999962, nVal = 83999996
LVV>8.4
LVV>

LVV>Понятно?
не понял, а при чем тут округление?? в моем примере fVal выводится нормально, без округления! да и потом 8,40 можно округлить до 8, но никак не до 8,39...
и почему тогда никакие другие значения fVal так хитро не округляются? почему только 8,40
Re[3]: магическое число??
От: Аноним  
Дата: 31.08.03 10:31
Оценка: 18 (1)
Здравствуйте, Аноним, Вы писали:

А>не понял, а при чем тут округление?? в моем примере fVal выводится нормально, без округления! да и потом 8,40 можно округлить до 8, но никак не до 8,39...

А>и почему тогда никакие другие значения fVal так хитро не округляются? почему только 8,40

А притом здесь округление, что в ЭВМ используется двоичное представление чисел.

Десятичное 8,4 = двоичное 1000,(0110) — периодичесая дробь; т. е. это число непредставимо в виде конечной двоичной дроби, и его приходится округлять до размера разрядной сетки.

Таким образом, на деле хранится что-то вроде 1000,011001100110011001100110011, и это округленное число может оказаться чуть больше или меньше исходного.
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
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Мда... проблемма примерно понятно, а как с этим бороться???


Проблемы нет. Просто типы данных нужно выбирать по задаче, либо уметь вручную округлять.
Re[6]: магическое число??
От: vvaizh http://izh-test.sourceforge.net/
Дата: 31.08.03 12:30
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Здравствуйте, Аноним, Вы писали:


А>>Мда... проблемма примерно понятно, а как с этим бороться???


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


он имеет ввиду, что работать скажем не с float а с double (уже практически стандарт, float забыл когда в последний раз видел)
или же вообще с longlong... только считать что у него в середине запятая..
http://izh-test.sourceforge.net/russian/introduction.html
Re[7]: магическое число??
От: Аноним  
Дата: 31.08.03 12:42
Оценка:
Здравствуйте, 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,... работу с базой поменять не могу, так как это творчество заказчика, и мне нужно все вписать в его базу
Re[5]: магическое число??
От: SWW Россия  
Дата: 01.09.03 05:30
Оценка: +1
А>Мда... проблемма примерно понятно, а как с этим бороться???

А как ты борешься с тем, что 2/3 не представима в виде конечной десятичной дроби? Тебя это не сильно беспокоит? Почему же тогда надо беспокоиться о том, что некоторые числа не представимы в виде конечной двоичной дроби?
Re[9]: магическое число??
От: LaptevVV Россия  
Дата: 01.09.03 05:45
Оценка:
Здравствуйте, Аноним, Вы писали:

А>На самом деле задача тривиальна... есть контрол, в котором пользовотель вводит стоимость некой услуги, это надо сохранить в базе (типа справочник), так вот когда пользовотель вводит 8,40, то в базе сохраняется 8,39, и еслественно его (пользовотеля ) такое абсолютно не устраивает.

А>то что пользовотель ввел преобразуется простейшим способом:
А>берем из Edit'а значение в char, а потом fVal = atof(char); при этом fVal = 8,40.
А>далее, в базу кладу только целые числа, для этого перед тем как положить умножаю fVal на 100, ну и естественно после того, как забираю делю на 100,... работу с базой поменять не могу, так как это творчество заказчика, и мне нужно все вписать в его базу
Еще раз: fVal = atof(char); при этом fVal = 8,40 — это только "на бумаге", то есть на экране. А внутри — как тут уже писали, и я приводил — 839999...
При присвоении к целому типу происходит ОТСЕЧЕНИЕ, поэтому перед присвоением надо сделать округление — вызвать функцию типа round (нодосуг сейчас самому искать в помощи) до второго знака после запятой. А потом уже можно присваивать целому.
Хочешь быть счастливым — будь им!
Без булдырабыз!!!
Re[10]: магическое число??
От: Кодт Россия  
Дата: 01.09.03 12:55
Оценка: 10 (1) -1 :)
Здравствуйте, LaptevVV, Вы писали:

LVV>При присвоении к целому типу происходит ОТСЕЧЕНИЕ, поэтому перед присвоением надо сделать округление — вызвать функцию типа round (нодосуг сейчас самому искать в помощи) до второго знака после запятой. А потом уже можно присваивать целому.


Отсечение — это нахождение ближайшего целого снизу, функция double ceil(double) или просто оператор int().
Округление — это ceil(f+0.5).
Есть еще нахождение ближайшего целого сверху — double floor(double)

Если нужно округлить с точностью до третьего разряда, то пишем ceil(f*1000 + 0.5)*0.001

В общем виде, округление с точностью до eps
#include <math.h>

inline double round(double f, double eps) { return ceil(f/eps + 0.5)*eps; }
Перекуём баги на фичи!
Re[11]: магическое число??
От: Аноним  
Дата: 01.09.03 12:57
Оценка: 26 (1)
Здравствуйте, Кодт, Вы писали:

К>Отсечение — это нахождение ближайшего целого снизу, функция double ceil(double) или просто оператор int().

К>Округление — это ceil(f+0.5).

К>Есть еще нахождение ближайшего целого сверху — double floor(double)


Ай-я-яй! В действительности все не так, как на самом деле! А как раз наоборот!
Re[12]: магическое число?? Извините.
От: Кодт Россия  
Дата: 01.09.03 13:30
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Ай-я-яй! В действительности все не так, как на самом деле! А как раз наоборот!


Сказывается бессонная ночь.
floor() — округление вниз
ceil() — вверх
Перекуём баги на фичи!
Re[8]: магическое число??
От: dad  
Дата: 26.07.05 12:30
Оценка:
А>Если речь идет о хранении денежных величин, то наиболее разумный подход — использовать тип данных с фиксированной точкой, сиречь масштабированные целые.

А>Например, при использовании типа long long int в Си (__int64 в MSVC++) с масштабным множителем 10000 можно представить любую мыслимую денежную сумму с точностью до 1/10000 руб. = 1/100 коп. без потери точности.


если речь идет о денежных величинах, то хранить надо все значения в минимальной денежной единице используемой валюты (копейки, центы, гроши)
Веру-ю-у! В авиацию, в научную революци-ю-у, в механизацию сельского хозяйства, в космос и невесомость! Веру-ю-у! Ибо это объективно-о! (Шукшин)
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.