Один вариант с Map
из base R
do.call(Map, c(f = c, asdf))
int a = 2, b = 3;
float c = static_cast<float>(a) / b; // need to convert 1 operand to a float
Пять эмпирических правил для запоминания:
ANSI C правила следующие:
большинство этих правил также относится к C++, хотя не все типы официально поддерживаются (все же).
Переполнение всегда является проблемой.Примечание. Тип результата совпадает с входными операндами, таким образом, все операции могут переполниться, таким образом, да действительно необходимо волноваться об этом (хотя язык не обеспечивает явного способа поймать этот случай.
Как примечание стороны:
Неподписанное подразделение не может переполниться, но подписанное подразделение может.
std::numeric_limits<int>::max() / -1 // No Overflow
std::numeric_limits<int>::min() / -1 // Will Overflow
В целом, если операнды будут иметь различные типы, то компилятор продвинет все самый большой или самый точный тип:
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
Это вызвано тем, что целочисленное деление выполняется сначала, затем результат продвинут для плавания для дополнения.
Подразделение целых чисел: бросьте любой из операндов, никакая потребность бросить их обоих. Если оба операнда являются целыми числами, операция деления является целочисленным делением, иначе это - подразделение с плавающей точкой.
Что касается водосливного вопроса, нет никакой потребности явно бросить, поскольку компилятор неявно делает это для Вас:
#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;
}
Можно просто бросить один из них. Это не имеет значения который все же.
Каждый раз, когда типы не соответствуют, "меньший" тип автоматически продвинут на "больший" тип, при этом плавающая точка "больше", чем целые типы.
В случае подразделения с плавающей точкой целая одна переменная имеет тип данных с плавающей точкой (плавание или дважды), затем другая переменная должна быть расширена до типа с плавающей точкой, и подразделение с плавающей точкой должно произойти; таким образом, нет никакой потребности бросить обоих к плаванию.
Однако я всегда бросал обоих к плаванию, так или иначе.
Я думаю, пока Вы бросаете только одну из этих двух переменных, компилятор будет вести себя правильно (По крайней мере, на компиляторах, которые я знаю).
Так весь из:
плавание c = (плавание) / b;
плавание c = / (плавание) b;
плавание c = (плавание) / (плавание) b;
будет иметь тот же результат.
Затем существуют более старые поврежденные мозгом типы как я, кто, имея необходимость использовать старомодные языки, просто легкомысленно пишет материал как
int a;
int b;
float z;
z = a*1.0*b;
, Конечно, это не универсально, хорошо только для в значительной степени просто этого случая.
Работая над критическими по отношению к безопасности системами, я склонен быть параноиком и всегда бросать оба фактора: плавание (a) / плавание (b) - на всякий случай некоторый тонкий глюк планирует укусить меня позже. Неважно, как хороший компилятор, как говорят, неважно, насколько четко определенный детали находятся в спецификациях официального языка. Паранойя: лучший друг программиста!
Необходимо ли бросить одну или две стороны? Ответ не диктует компилятор. Это должно знать точное, precse правила. Вместо этого ответ должен продиктовать человек, который прочитает код позже. По этой причине один, бросает обе стороны к тому же типу. Неявное усечение могло бы быть достаточно видимо, так, чтобы брошенный могло быть избыточным.
, например, это плавание броска-> интервал очевиден.
int a = float(foo()) * float(c);