ошибка подсчёта
От: emx  
Дата: 16.02.04 13:46
Оценка:
int main(void)
{
int a,x,yb;
printf("a=");
scanf("%i", &a);
printf("x=");
scanf("%i", &x);
printf("\r\ny=");
yb=a*(x*x-6);
printf("%i\n",yb);
}
если вводить большие числа (типа а=111111, х=111111) — считает неправильно
где копать?
Re: ошибка подсчёта
От: Bell Россия  
Дата: 16.02.04 13:57
Оценка:
Здравствуйте, emx, Вы писали:

emx>int main(void)

emx>{
emx>int a,x,yb;
emx>printf("a=");
emx>scanf("%i", &a);
emx>printf("x=");
emx>scanf("%i", &x);
emx>printf("\r\ny=");
emx>yb=a*(x*x-6);
emx>printf("%i\n",yb);
emx>}
emx>если вводить большие числа (типа а=111111, х=111111) — считает неправильно
emx>где копать?

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

ЗЫ
На многих платфоммах int — это 4 байта, а диапазон возможных значений — [-2147483648, 2147483647].
Любите книгу — источник знаний (с) М.Горький
Re: банальное переполнение int.
От: Croc Россия  
Дата: 16.02.04 13:57
Оценка: +1
Здравствуйте, emx, Вы писали:

emx>yb=a*(x*x-6);

emx>если вводить большие числа (типа а=111111, х=111111) — считает неправильно


Прикинь порядок а*x*x с такими числами. Получится пятнадцатый порядок.
А самое большое число, которое влезает в 32х-битный int это 2147483647*, оно на 6 порядков меньше.
"Обычный" int (он же long) в MS VC 6.0 — 32х-битный.

*См MSDN, "Data Type Ranges"
Re: ошибка подсчёта
От: GarryIV  
Дата: 16.02.04 13:58
Оценка:
Здравствуйте, emx! Вы писали:

e> int main(void)

e> {
e> int a,x,yb;
e> printf("a=");
e> scanf("%i", &a);
e> printf("x=");
e> scanf("%i", &x);
e> printf("\r\ny=");
e> yb=a*(x*x-6);
e> printf("%i\n",yb);
e> }
e> если вводить большие числа (типа а=111111, х=111111) — считает
e> неправильно где копать?

Переполнение однако... Используй вместо int что нибудь побольше.
Posted via RSDN NNTP Server 1.8 beta
WBR, Igor Evgrafov
Re[2]: ошибка подсчёта
От: emx  
Дата: 16.02.04 14:14
Оценка:
я и __int64 пробовал — не помогает
(компилятор bcb6)
Re: ошибка подсчёта
От: LaptevVV Россия  
Дата: 16.02.04 14:21
Оценка: 32 (1)
Здравствуйте, emx, Вы писали:

emx>где копать?

Копать здесь

Однако программирование полно «подводных камней», о которых начинающий программист не подозревает. Одной из первых проблем, с которыми приходится столкнуться, является переполнение. Допустим, в нашей программе есть переменная a типа float, которая содержит величину, близкую к предельной, например, 1037. Что произойдет, если мы попытаемся выполнить такой оператор:

cout << a*1000 << endl;


Пока мы запускаем программу в интегрированной среде Borland C++ 3.1, операция не выполняется! Оператор выводит на экран значение 1е+37. Но стоит нам запустить программу независимо от среды, мы получаем сообщение:
Floating point error: Overflow. (Ошибка плавающей точки: Переполнение.)
Abnormal program termination (Ненормальное завершение программы)
Очевидно, результат просто не может поместиться в переменную типа float. Такие ситуации называются переполнением. Понятно, что аналогичная картина может возникнуть и при использовании других плавающих типов. Интегрированная среда просто отслеживает такую ситуацию и не дает программе совершить аварию. Рассмотрим аналогичную ситуацию с целыми числами. Заглянув в помощь системы Borland C++ 3.1, обнаруживаем, что целые числа типа int изменяются от -32768 до +32767. Посмотрим, что получится, если мы будем работать на границах диапазона.

cout << +32767+1 << endl;
cout << -32768-1 << endl;

Первый оператор выводит на экран отрицательное число -32768, а второй — положительное число 32767. Таким образом, мы наблюдаем, что при добавлении 1 к правой (положительной) границе диапазона получается отрицательное число — левая граница диапазона. При вычитании 1 из левой (отрицательной) границы диапазона получаем, соответственно, правую границу диапазона. От размера чисел эта ситуация не зависит — то же самое происходит и с числами типа long, и short.
Аналогичную картину наблюдаем и для беззнаковых чисел unsigned int, которые изменяются в диапазоне от 0 до 65535. Оператор

cout << 65535u+1 << endl;

выдает на экран ноль. Аналогично оператор

cout << 0u-1 << endl;

выводит число 65535. Самое неприятное, что не выводится никаких сообщений или предупреждений ни при трансляции, ни при выполнении программы.
С типом char — аналогичные проблемы, которые усугубляются «знаковостью- беззнаковостью», принятой по умолчанию. Диапазон «маленьких чисел» изменяется от -128 до 127. Однако ни системы фирмы Borland, ни Visual C++ 6 не «протестуют», если в программе встречается, например, такой оператор:

char ch = 255;

Вывод ch как целого числа показывает на экране -1. Справедливости ради надо сказать, что Visual C++ 6 выдает предупреждение
warning C4305: 'initializing' : truncation from 'const int' to 'char'
‘инициализация’: усечение 'const int' до 'char'
Иногда недоумение вызывают совершенно безобидные выражения. Например, переменная d в следующем операторе:
double d = 15/2;
будет равна 7, а не 7.5. А все дело в том, что выражение 15/2 — это деление целых чисел и выполняется с отсечением. И только после выполнения операции результат (целое число) преобразуется в дробное типа double. Чтобы таких ошибок не было, необходимо в выражениях задавать дробные константы:
double d = 15.0/2;
или
double d = 15/2.0;
Операция запятая тоже может спровоцировать ошибку, например
double d; d = 3,141592653;
Переменная d равно 3, а не «пи», как задумывал программист — вместо точки написана запятая.

Написано в моей книжке здесь
Хочешь быть счастливым — будь им!
Без булдырабыз!!!
Re[2]: ошибка подсчёта
От: Кодт Россия  
Дата: 16.02.04 14:31
Оценка: :))
Здравствуйте, LaptevVV, Вы писали:

emx>>где копать?

LVV>Копать здесь

Цитата из твоей книги?

LVV>Допустим, в нашей программе есть переменная a типа float, которая содержит величину, близкую к предельной, например, 1037.

кто бы мог подумать...

LVV>double d; d = 3,141592653;
LVV>Переменная d равно 3, а не «пи», как задумывал программист — вместо точки написана запятая.

Какой красивый баг! Супер супер супер . Не послать ли его в микрософт?
Перекуём баги на фичи!
Re[3]: ошибка подсчёта
От: LaptevVV Россия  
Дата: 16.02.04 15:00
Оценка:
Здравствуйте, Кодт, Вы писали:

К>Здравствуйте, LaptevVV, Вы писали:


emx>>>где копать?

LVV>>Копать здесь

К>Цитата из твоей книги?


К>

LVV>>Допустим, в нашей программе есть переменная a типа float, которая содержит величину, близкую к предельной, например, 1037.

К>кто бы мог подумать...
Не посмотрел. Кстати, как принято на RSDN верхний индекс обозначать? ИМХО подходит 10^37
К>

LVV>>double d; d = 3,141592653;
LVV>>Переменная d равно 3, а не «пи», как задумывал программист — вместо точки написана запятая.

К>Какой красивый баг! Супер супер супер . Не послать ли его в микрософт?
Тут где-то топик был — насыпать приколов по С++. Я с десяток отсыпал, но, как втидишь, в заначке еще остались.
Туда бы...
Хочешь быть счастливым — будь им!
Без булдырабыз!!!
Re[4]: ошибка подсчёта
От: retalik www.airbandits.com/
Дата: 16.02.04 23:19
Оценка:
Здравствуйте, LaptevVV, Вы писали:

LVV>>>double d; d = 3,141592653;

LVV>Тут где-то топик был — насыпать приколов по С++. Я с десяток отсыпал, но, как втидишь, в заначке еще остались.
Из личного зверинца (самого покусали в детстве):
const pi = 3.141592653;

Взгляд не спотыкается совершенно! Искал ошибку долго...
При расчетах pi==3 (забыл double)
Успехов,
Виталий.
Re[5]: ошибка подсчёта
От: mraleh Россия  
Дата: 17.02.04 07:31
Оценка:
Здравствуйте, retalik, Вы писали:

R>Здравствуйте, LaptevVV, Вы писали:


LVV>>>>double d; d = 3,141592653;

LVV>>Тут где-то топик был — насыпать приколов по С++. Я с десяток отсыпал, но, как втидишь, в заначке еще остались.
R>Из личного зверинца (самого покусали в детстве):
R>
R>const pi = 3.141592653;
R>

R>Взгляд не спотыкается совершенно! Искал ошибку долго...
R>При расчетах pi==3 (забыл double)
Аналогично было как-то.
Хорошо, что сейчас по новому стандарту попасться на этом нельзя.
... << RSDN@Home 1.1.0 stable >>
Re: ошибка подсчёта
От: emx  
Дата: 19.02.04 11:05
Оценка:
ёлки-палки, так что ж делать? на вопрос-то не ответили :(
и ещё:
float yc; // пробовал и double
yc=a/(x*x+6);
printf("%.4f\n",yc);
ввожу х=5 и а=5, ответ пишет 0,0000, в чём ж дело?
Re[2]: ошибка подсчёта
От: jazzer Россия Skype: enerjazzer
Дата: 19.02.04 11:27
Оценка:
Здравствуйте, LaptevVV, Вы писали:

LVV>Здравствуйте, emx, Вы писали:


emx>>где копать?

LVV>Копать здесь

LVV>

LVV>Операция запятая тоже может спровоцировать ошибку, например
LVV>double d; d = 3,141592653;
LVV>Переменная d равно 3, а не «пи», как задумывал программист — вместо точки написана запятая.


последний пример можно расширить и задавать на интервью:

чему будут равны a и b после следующих операций:

double a = 0, b = 0;
b = a = 3,1415926;
b = (a = 3,1415926);

jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got
  If you always do  what you always did
Re[2]: ошибка подсчёта
От: Кодт Россия  
Дата: 19.02.04 11:36
Оценка: 2 (1)
Здравствуйте, emx, Вы писали:

emx>ёлки-палки, так что ж делать? на вопрос-то не ответили

emx>и ещё:
emx>float yc; // пробовал и double
emx>yc=a/(x*x+6);
emx>printf("%.4f\n",yc);
emx>ввожу х=5 и а=5, ответ пишет 0,0000, в чём ж дело?

В арифметике, ёлки палки!!!

a — целое.
(x*x+6) — целое.

Сколько будет 5/31 ? Знаешь, сколько? НОЛЬ!!!
Потому что это целочисленное деление.

Хочешь получить вещественный результат — так и пиши соответственно
yc = ((double)a) / (вся эта ботва с иксами)
Перекуём баги на фичи!
Re[3]: ошибка подсчёта
От: Вадим Никулин Россия Здесь
Дата: 19.02.04 13:56
Оценка:
Здравствуйте, Кодт, Вы писали:

К>a — целое.

К>(x*x+6) — целое.

К>
К>yc = ((double)a) / (вся эта ботва с иксами)
К>


А еще можно
   a/(x*x+6.0)
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.