¿Cuál es el casting de la orden de las operaciones en aritmética en c++?

0

Pregunta

¿Por qué

  1. result = static_cast<double>(1 / (i+1))

volver int en C++ ¿y por qué

  1. result = 1 / (i+static_cast<double>(1))

volver double? Específicamente ¿por qué después de la fundición +-operación suficiente para producir un double. ¿Por qué no es requerido antes de que el + o en el numerador así? Es static_cast la forma preferida de casting?

Código:

double harmonic(int n) {
  double result = 0;
  for (int i = 0; i < n; i++) {
    result += 1 / static_cast<double>(i+1);
  }
  return result;
}
arithmetic-expressions c++ casting types
2021-11-21 13:17:43
3

Mejor respuesta

2

No hay tal cosa como "casting orden" debido a que el tipo de una expresión depende de sus operandos. Sencillamente, si un binario operador aritmético acepta dos operandos de diferentes tipos, a continuación, el tipo más pequeño se convierte implícitamente en el más amplio de tipo

En result = static_cast<double>(1 / (i+1)) se analiza como esta

  • i + 1 es un int la expresión ya que ambos i y 1 son de tipo int
  • 1 / (i + 1) devuelve int por la misma razón
  • A continuación, el resultado de 1 / (i + 1) es estáticamente yeso para double

OTOH en result = 1 / (i+static_cast<double>(1)) es como este

  • 1 es arrojado a la double
  • i + static_cast<double>(1) devuelve double porque i es arrojado a la double debido a que el otro operando
  • 1 / (i+static_cast<double>(1)) es un double expresión por la misma razón

Pero no hay un elenco como el que. Es mejor hacer 1 / (i + 1.0) en su lugar

La regla completa es como este

  • Si alguno de los operandos ha ámbito tipo de enumeración, no se realiza la conversión: el otro operando y el tipo de retorno debe tener el mismo tipo de
  • De lo contrario, si alguno de los operandos es long doubleel otro operando se convierte en long double
  • De lo contrario, si alguno de los operandos es doubleel otro operando se convierte en double
  • De lo contrario, si alguno de los operandos es floatel otro operando se convierte en float
  • De lo contrario, el operando tiene tipo entero (porque bool, char, char8_t, char16_t, char32_t, wchar_ty sin ámbito de la enumeración se promovieron en este punto) y la integral de las conversiones son aplicados para producir el tipo común, de la siguiente manera:
    • Si ambos operandos son firmado o ambos no están firmados, el operando con menor rango de conversión se convierte en el operando con la mayor conversión de enteros rango
    • De lo contrario, si el unsigned operando la conversión de rango es mayor o igual que el rango de conversión de la firma operando, el firmado operando se convierte en el unsigned operando del tipo.
    • De lo contrario, si la firma del operando del tipo puede representar todos los valores de la unsigned operando, el unsigned operando se convierte en la firma del operando del tipo
    • De lo contrario, ambos operandos son convertidos sin signo contraparte de la firma operando del tipo.

La conversión de rango por encima de los aumentos en orden bool, signed char, short, int, long, long long. El rango de cualquier tipo unsigned es igual al rango de la correspondiente firmado tipo. El rango de char es igual al rango de signed char y unsigned char. Las filas de char8_t, char16_t, char32_ty wchar_t son iguales a las filas de sus subyacentes tipos.

Operadores aritméticos

2021-11-21 13:34:10

Genial, gracias! Esta es exactamente la respuesta que yo estaba buscando. He encontrado el truco con 1.0 especialmente útil!
DataFace
1
static_cast<double>(1 / (i+1));

En primer lugar, 1 / (i+1) conseguir evaluar. Porque 1 es un int y i+1 es un intasí que esta es la división entera, por lo que 1/(i+1) es un int. El resultado es, a continuación, convertir en un double. Así que, técnicamente, static_cast<double>(1 / (i+1)); devuelve un doublepero el resultado es perdido porque 1/(i+1) es la división entera

result += 1 / static_cast<double>(i+1);

Ahora porque static_cast<double>(i+1) es un doble, 1 / static_cast<double>(i+1); ahora es de punto flotante de división, así 1 / static_cast<double>(i+1); es un double

2021-11-21 13:26:20

Y, por supuesto, 1.0 /(i + 1) es incluso mejor.
Pete Becker
1

Usted debe ser consciente de División de Enteros

Usted puede utilizar este código para ver, que devuelve un double. Sin embargo, debido a la división de enteros, siempre será cero (nan).

#include <iostream>

using std::cout;

int main()
{
    int i = 5;
    cout << typeid(static_cast<double>(1 / (i+1))).name() << "\n"; // d for double
    return 0;
}

Usted puede evitar la división entera, por no dividir dos enteros. Para ello es suficiente si uno de ellos es doble.

int + double == double
double + int == double
int / double == double
double / int == double

Así que usted puede ver, no es suficiente para emitir un sumando el doble, con el fin de convertir la totalidad de la expresión en una cama doble, que no es siempre cero.

2021-11-21 13:30:50

En otros idiomas

Esta página está en otros idiomas

Русский
..................................................................................................................
Italiano
..................................................................................................................
Polski
..................................................................................................................
Română
..................................................................................................................
한국어
..................................................................................................................
हिन्दी
..................................................................................................................
Français
..................................................................................................................
Türk
..................................................................................................................
Česk
..................................................................................................................
Português
..................................................................................................................
ไทย
..................................................................................................................
中文
..................................................................................................................
Slovenský
..................................................................................................................