Каких переменных я должен преобразовать тип при выполнении математических операций в C/C++?

Один вариант с Map из base R

do.call(Map, c(f = c, asdf))
18
задан Jeremy Ruten 29 October 2008 в 03:55
поделиться

9 ответов

Вопрос 1: подразделение Плавающее

int a = 2, b = 3;
float c = static_cast<float>(a) / b;  // need to convert 1 operand to a float

Вопрос 2: Как компилятор работает

Пять эмпирических правил для запоминания:

  • Арифметические операции всегда выполняются на значениях того же типа.
  • тип результата совпадает с операндами (после продвижения)
  • , самые маленькие арифметические операции типа выполняются на, международный
  • ANSCI C (и таким образом C++) значение использования, сохраняющее целочисленное продвижение.
  • Каждая операция сделана в изоляции .

ANSI C правила следующие:
большинство этих правил также относится к C++, хотя не все типы официально поддерживаются (все же).

  • , Если любой операнд длинен двойной другой, преобразовывается в длинный двойной .
  • , Если любой операнд двойной другой, преобразовывается в двойной .
  • , Если любой операнд , плавание другой преобразовывается в плавание .
  • , Если любой операнд не подписан длинный длинный другой, преобразовывается в [1 110] неподписанный длинный длинный .
  • , Если любой операнд длинен длинный другой, преобразовывается в [1 112] длинный длинный .
  • , Если любой операнд не подписан длинный другой, преобразовывается в [1 114] неподписанный длинный .
  • , Если любой операнд длинен другой, преобразовывается в [1 116] длинный .
  • , Если любой операнд , неподписанный интервал другой преобразовывается в [1 118] неподписанный интервал .
  • Иначе оба операнды преобразовываются в [1 120] интервал .

Переполнение

Переполнение всегда является проблемой.Примечание. Тип результата совпадает с входными операндами, таким образом, все операции могут переполниться, таким образом, да действительно необходимо волноваться об этом (хотя язык не обеспечивает явного способа поймать этот случай.

Как примечание стороны:
Неподписанное подразделение не может переполниться, но подписанное подразделение может.

std::numeric_limits<int>::max() / -1  // No Overflow
std::numeric_limits<int>::min() / -1  // Will Overflow
26
ответ дан 30 November 2019 в 06:26
поделиться

В целом, если операнды будут иметь различные типы, то компилятор продвинет все самый большой или самый точный тип:

If one number is...   And the other is...    The compiler will promote to...
-------------------   -------------------    -------------------------------
char                  int                    int
signed                unsigned               unsigned
char or int           float                  float
float                 double                 double

Примеры:

char       + int             ==> int
signed int + unsigned char   ==> unsigned int
float      + int             ==> float

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

4.0 + 5/3  =  4.0 + 1 = 5.0

Это вызвано тем, что целочисленное деление выполняется сначала, затем результат продвинут для плавания для дополнения.

13
ответ дан 30 November 2019 в 06:26
поделиться

Подразделение целых чисел: бросьте любой из операндов, никакая потребность бросить их обоих. Если оба операнда являются целыми числами, операция деления является целочисленным делением, иначе это - подразделение с плавающей точкой.

Что касается водосливного вопроса, нет никакой потребности явно бросить, поскольку компилятор неявно делает это для Вас:

#include <iostream>
#include <limits>

using namespace std;
int main()
{
    signed int a = numeric_limits<signed int>::max();
    unsigned int b = a + 1; // implicit cast, no overflow here
    cout << a << ' ' <<  b << endl;
    return 0;
}
2
ответ дан 30 November 2019 в 06:26
поделиться

Можно просто бросить один из них. Это не имеет значения который все же.

Каждый раз, когда типы не соответствуют, "меньший" тип автоматически продвинут на "больший" тип, при этом плавающая точка "больше", чем целые типы.

5
ответ дан 30 November 2019 в 06:26
поделиться

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

Однако я всегда бросал обоих к плаванию, так или иначе.

1
ответ дан 30 November 2019 в 06:26
поделиться

Я думаю, пока Вы бросаете только одну из этих двух переменных, компилятор будет вести себя правильно (По крайней мере, на компиляторах, которые я знаю).

Так весь из:

плавание c = (плавание) / b;

плавание c = / (плавание) b;

плавание c = (плавание) / (плавание) b;

будет иметь тот же результат.

1
ответ дан 30 November 2019 в 06:26
поделиться

Затем существуют более старые поврежденные мозгом типы как я, кто, имея необходимость использовать старомодные языки, просто легкомысленно пишет материал как

int a;
int b;
float z;

z = a*1.0*b;

, Конечно, это не универсально, хорошо только для в значительной степени просто этого случая.

1
ответ дан 30 November 2019 в 06:26
поделиться

Работая над критическими по отношению к безопасности системами, я склонен быть параноиком и всегда бросать оба фактора: плавание (a) / плавание (b) - на всякий случай некоторый тонкий глюк планирует укусить меня позже. Неважно, как хороший компилятор, как говорят, неважно, насколько четко определенный детали находятся в спецификациях официального языка. Паранойя: лучший друг программиста!

1
ответ дан 30 November 2019 в 06:26
поделиться

Необходимо ли бросить одну или две стороны? Ответ не диктует компилятор. Это должно знать точное, precse правила. Вместо этого ответ должен продиктовать человек, который прочитает код позже. По этой причине один, бросает обе стороны к тому же типу. Неявное усечение могло бы быть достаточно видимо, так, чтобы брошенный могло быть избыточным.

, например, это плавание броска-> интервал очевиден.

int a = float(foo()) * float(c); 
0
ответ дан 30 November 2019 в 06:26
поделиться