Форум программистов, компьютерный форум, киберфорум
C для начинающих
Войти
Регистрация
Восстановить пароль
Другие темы раздела
C (СИ) Вычислить расстояние между двумя точками с заданными координатами https://www.cyberforum.ru/ c-beginners/ thread1267066.html
Вычислить расстояние между двумя точками с координатами x1, y1 и x2, y2. Исходные данные и результат вывести в табличной форме. Добавлено через 42 минуты люди очень нужна помощь(
C (СИ) Не считается произведение
Не считает произведение где ошибка? И если не сложно напишите вывод отсортированного массива. #include <stdio.h> #include <math.h> int main(void) { const int N = 5; double arr; ...
Cортировка Шелла / Древовидная, определить количество перестановок и присваиваний C (СИ)
Заданы 3 массива из 200 эл. 1 упорядоченный.2масссив 200,199,198 и тд. 3 рандомный( как задать массив рандомный без повторений?). Надо вычислить кол-во перестановок и присваиваний сл методами...
C (СИ) Зашифровать слово данного предложения по принципу "сдвиг на 2 символа" С клавиатуры задаётся предложение.Зашифровать слово данного предложения по принципу "сдвиг на 2 символа": a-c;b-d;c-e; и тд. Подскажите пожалуйста как делать. https://www.cyberforum.ru/ c-beginners/ thread1266942.html
C (СИ) Запись в файл из нескольких потоков https://www.cyberforum.ru/ c-beginners/ thread1266894.html
Здравствуйте! Можно ли писать в один и тот же файл из нескольких потоков без синхронизации? Была идея завести переменную флаг на событие открыт ли файл, но можно ли сделать это штатными средствами...
Составить алгебраические выражения с помощью стандартных математических функций языка C (СИ)
Помогите решить задачу, если не трудно, пожалуйста) "Для приведенных ниже вариантов необходимо составить алгебраические выражения с помощью стандартных математических функций языка С." h - {a}^{3}...
C (СИ) Реализация алгоритма base64
Я скачал реализацию алгоритма кодирования base64: static const char basis_64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; int Base64encode_len(int len) { ...
C (СИ) Не выводится на экран ответ программы, приложение вместо этого закрывается #include <stdio.h> #include <stdlib.h> int main() { int age; printf("How old are you?"); scanf("%d", &age); if (age < 100) { printf("You are very young"); https://www.cyberforum.ru/ c-beginners/ thread1266807.html
C (СИ) Нахождение чисел делящихся на 7 в интервале https://www.cyberforum.ru/ c-beginners/ thread1266787.html
Добрый вечер. Сразу прошу прощения, если не правильно оформил пост и/или написал не в том разделе. Помогите, пожалуйста, написать код программы. программа - курсовая работа. Нужно очень срочно....
C (СИ) Записи, содержащие данные о студентах-спортсменов института. Найти ошибку в цикле С клавиатуры ввести последовательность записей, содержащих данные о студентах-спортсменов института: <Фамилия, имя>, <Год рождения>, <Вид спорта>, <Разряд>. Распечатать введенные данные в форме... https://www.cyberforum.ru/ c-beginners/ thread1266689.html
Evg
Эксперт CАвтор FAQ
21098 / 8115 / 628
Регистрация: 30.03.2009
Сообщений: 22,440
Записей в блоге: 30
12.10.2014, 14:06 0

Распространенные ошибки

12.10.2014, 14:06. Просмотров 68081. Ответов 63
Метки (Все метки)

Ответ

10. "Неожиданное" целочисленное деление в арифметических выражениях.
Следует помнить, что результат деления целого на целое - тоже целое:
C
1
2
3
4
5
int n;double y;
n=2;
y = 1/n;// y будет равен нулю
y = pow(y, 1/3 ); // возведение в нулевую степень
z = y + n/(n+1); // прибавляется ноль
Рекомендации:
Все константы, которые явно не должны быть целыми, делайте действительными
(записывайте с точкой, первое время можете даже после точки ставить нуль 1.0 ):
C
1
2
3
4
5
int n;double y;
n=2;
y = 1./n;// y будет равен 0.5
y=pow(y, 1./3. ); //извлечение корня кубического
z=y + n/(n+ 1. ); // прибавляется 0.666666666666
Там, где в выражении нет констант, используйте оператор приведения
C
1
2
3
4
int n,m;
n=1;
m=2;
double y = (double)n/m;

Пояснения, почему так происходит.

Во всех двухаргументных арифметических операциях (кроме операций сдвига) оба аргумента должны иметь один и тот же тип. Если аргументы имеют разный тип, то компилятор строит неявное приведение типа для одного их аргументов, чтобы в конечном итоге выполнить арифметическую операцию над значениями одного и того же типа. Чтобы выяснить, который из двух аргументов нужно приводить к типу другого, в стандарте языка существуют правила, которые в отдельных тонких моментах даже различаются для Си и Си++. В общем виде они довольно сложные для восприятия начинающими, а потому сделаю лишь краткое пояснение.

В случае различных типов один из типов является более "широким", чем другое. А потому в двухаргументной операции всегда аргумент более "узкого" типа приводится к более "широкому" типу. Проверка идёт примерно в таком порядке:
  • Вещественный тип всегда считается более широким, чем целочисленный
  • Когда оба типа вещественные или оба целочисленные, то тип с большим размером всегда считается более широким, чем тип с меньшим размером
  • В случае равенства размеров для целочисленных типов беззнаковый тип считается более широким, чем знаковый

В итоге код

C
float f;
int i;
unsigned u;
long long ll;
x + f;
u + f;
i + u;
ll + u;
эквивалентен

C
int i;
unsigned u;
float f;
((float)x) + f; /* тип результата - float */
((float)u) + f; /* тип результата - float */
((unsigned)i) + u; /* тип результата - unsigned */
ll + ((long long)u); /* тип результата - long long */
Если мы вернёмся к делению, то следующий код

C
int a, b;
float f;
f = a / b;
эквивалентен

C
int a, b, tmp;
float f;
/* сначала выполняем целочисленное деление
 * (при котором отбрасывается остаток) */
tmp = a / b;
/* и только потом полученный результат (с утерянной
 * дробной частью) преобразуется в вещественный тип */
f = (float) tmp;
А потому, чтобы выполнить нормальное вещественное деление нужно хотя бы один из аргументов превратить в вещественный тип, после чего второй аргумент превратится в вещественный тип автоматически по выше описанным правилам. Т.е. явно написать

C
int a, b;
float f;
f = ((float)a) / b;
или

C
int a, b;
float f;
f = a / ((float)b);
что будет эквивалентно

C
int a, b;
float f;
f = ((float)a) / ((float)b);
Если один из аргументов является константой, то можно написать её в виде "3.0" (с вещественной дробной частью), что автоматически приведёт её тип к вещественному

Вернуться к обсуждению:
Распространенные ошибки
8
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
12.10.2014, 14:06
Готовые ответы и решения:

Распространенные ошибки
Оглавление Ошибки этапа компиляции Программа не компилируется или компилируется с...

безопасность и распространенные ошибки
Тут наткнулся на очень интересные тексты: http://werad.narod.ru/articles/programm6.html ...

Распространенные ошибки SEO и ASP.NET 2.0
Здравствуйте, существуют несколько СЕО проблем при использовании ASP.NET, ниже я опишу эти...

Самые распространенные строки
type Mytype = record name:string; surname:string; end; var Students:Mytype; ...

63
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2020, vBulletin Solutions, Inc.