Qual è il casting ordine delle operazioni in aritmetica in c++?

0

Domanda

Perché

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

ritorno int in C++, e perché

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

ritorno double? In particolare perché dopo il casting +-il funzionamento è sufficiente a produrre un double. Perché non è richiesto prima che il + o al numeratore così? È static_cast il modo preferito di casting?

Codice:

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

Migliore risposta

2

Non c'è nessuna tale cosa come "casting ordine", perché il tipo di un'espressione dipende dalla sua operandi. Messo semplicemente, se l'aritmetica binaria operatore accetta due operandi di diversi tipi, poi il tipo più piccolo sarà convertito implicitamente più ampio tipo

In result = static_cast<double>(1 / (i+1)) è analizzato come questo

  • i + 1 è un int espressione in quanto entrambi i e 1 sono di tipo int
  • 1 / (i + 1) restituisce int per lo stesso motivo
  • Quindi il risultato di 1 / (i + 1) è staticamente il cast double

OTOH in result = 1 / (i+static_cast<double>(1)) è come questo

  • 1 cast double
  • i + static_cast<double>(1) restituisce double perché i cast double a causa di l'altro operando
  • 1 / (i+static_cast<double>(1)) è un double espressione per lo stesso motivo

Ma nessuno del cast del genere. Meglio non fare 1 / (i + 1.0) invece

Il regolamento completo è questo

  • Se uno dei due operandi ha scovato tipo di enumerazione, non viene eseguita alcuna conversione: l'altro operando e il tipo di ritorno devono avere lo stesso tipo di
  • Altrimenti, se uno degli operandi è long doublel'altro operando viene convertito long double
  • Altrimenti, se uno degli operandi è doublel'altro operando viene convertito double
  • Altrimenti, se uno degli operandi è floatl'altro operando viene convertito float
  • In caso contrario, l'operando è di tipo intero (perché bool, char, char8_t, char16_t, char32_t, wchar_te di ruolo di enumerazione sono stati promossi a questo punto) e integrale per le conversioni vengono applicati per produrre il tipo di comune, come segue:
    • Se entrambi gli operandi sono firmati o entrambi sono firmati, operando con minore conversione rango è convertito operando con il maggior numero intero di conversione rank
    • In caso contrario, se il unsigned operando la conversione rank è maggiore o uguale al rango di conversione del sottoscritto operando, firmato operando è convertito al unsigned operando di tipo.
    • In caso contrario, se il sottoscritto operando tipo può rappresentare tutti i valori della unsigned operando, senza segno degli operandi è convertito alla firma di un operando di tipo
    • In caso contrario, entrambi gli operandi sono convertiti al unsigned contropartita della firma di un operando di tipo.

La conversione di rango sopra aumenta in ordine bool, signed char, short, int, long, long long. Il rango di ogni tipo senza segno è pari al rango del corrispondente tipo signed. Il rango di char è uguale al rango di signed char e unsigned char. La truppa di char8_t, char16_t, char32_te wchar_t sono uguali ai ranghi dei loro sottostanti tipi.

Gli operatori aritmetici

2021-11-21 13:34:10

Grande, grazie! Questa è esattamente la risposta che stavo cercando. Ho trovato il trucco con 1.0 particolarmente utile!
DataFace
1
static_cast<double>(1 / (i+1));

Prima, 1 / (i+1) ottenere valutare. Perché 1 è un int e i+1 è un intquindi questa è la divisione di interi, in modo 1/(i+1) è un int. Il risultato viene poi etichettato in un double. Quindi, tecnicamente, static_cast<double>(1 / (i+1)); restituisce un doublema il risultato è perso a causa 1/(i+1) è la divisione di interi

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

Ora, perché static_cast<double>(i+1) è un doppio 1 / static_cast<double>(i+1); è ora in virgola mobile divisione, così 1 / static_cast<double>(i+1); è un double

2021-11-21 13:26:20

E, naturalmente, 1.0 /(i + 1) è anche meglio.
Pete Becker
1

Si dovrebbe essere consapevoli di Integer, Divisione

È possibile utilizzare questo codice per vedere che effettivamente restituisce un double. Tuttavia, a causa della divisione di numeri interi, sarà sempre zero (o 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;
}

È possibile evitare la divisione di interi, da non dividere due numeri interi. Perciò è sufficiente se uno di loro è un doppio.

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

Così si può vedere, è sufficiente solo il cast di un addendo del doppio, per girare l'intera espressione in un doppio, che non è sempre uguale a zero.

2021-11-21 13:30:50

In altre lingue

Questa pagina è in altre lingue

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