Ceea ce este decisiv pentru operațiunile în aritmetica în c++?

0

Problema

De ce nu

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

reveni int în C++ și de ce nu

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

reveni double? În mod concret de ce este după turnare +-funcționarea suficient pentru a produce o double. De ce nu este necesară înainte de + sau la numărător la fel de bine? Este static_cast modul preferat de turnare?

Cod:

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

Cel mai bun răspuns

2

Nu există nici un astfel de lucru ca "casting pentru" deoarece tipul unei expresii depinde de operanzi. Pune pur și simplu, dacă un operator aritmetic binar acceptă doi operanzi de tipuri diferite, atunci cel mai mic tip va fi implicit convertit la mai largi de tip

În result = static_cast<double>(1 / (i+1)) este analizat astfel de prognoze

  • i + 1 este o int expresia din ambele i și 1 sunt de tip int
  • 1 / (i + 1) returnează int pentru același motiv
  • Apoi rezultatul 1 / (i + 1) este static aruncat la double

OTOH în result = 1 / (i+static_cast<double>(1)) e ca și cum acest

  • 1 este aruncat la double
  • i + static_cast<double>(1) se întoarce double pentru că i este aruncat la double din cauza celălalt operand
  • 1 / (i+static_cast<double>(1)) este un double expresia pentru același motiv

Dar nu arunca unul ca asta. E mai bine să facă 1 / (i + 1.0) în loc

Complet, regula este ca acest

  • Dacă operandul are ca domeniu de tip enumerare, nici o conversie este efectuată de: celalalt operand și tipul de retur trebuie să fie de același tip
  • În caz contrar, dacă oricare dintre operanzi este de long double, celălalt operand este convertit la long double
  • În caz contrar, dacă oricare dintre operanzi este de double, celălalt operand este convertit la double
  • În caz contrar, dacă oricare dintre operanzi este de float, celălalt operand este convertit la float
  • În caz contrar, operand are tipul întreg (pentru că bool, char, char8_t, char16_t, char32_t, wchar_tși nescopate enumerare au fost promovate în acest moment) și integrantă conversii sunt aplicate pentru a produce frecvent tip, după cum urmează:
    • Dacă ambii operanzi sunt semnate sau ambele sunt nesemnate, operandul cu mai puțin de conversie rang este convertit la operand cu cel mai mare număr întreg de conversie rang
    • În caz contrar, dacă nesemnate operand este de conversie rang este mai mare sau egală cu rang de conversie a semnat operand, semnat operand este convertit la unsigned operand este de tip.
    • În caz contrar, dacă a semnat operand este de tip poate reprezenta toate valorile nesemnate operand, nesemnate operand este convertit la semnat operand este de tip
    • În caz contrar, ambii operanzi sunt convertit la unsigned omologul a semnat operand este de tip.

De conversie rang mai sus crește, în scopul de bool, signed char, short, int, long, long long. Rangul de orice tip unsigned este egal cu rangul corespunzător semnat de tip. Gradul de char este egal cu rangul de signed char și unsigned char. În rândurile de char8_t, char16_t, char32_tși wchar_t sunt egale între rândurile care stau la baza lor tipuri.

Operatori aritmetici

2021-11-21 13:34:10

Minunat, multumesc! Acest lucru este exact răspunsul pe care îl căutam. Am găsit trucul cu 1.0 deosebit de util!
DataFace
1
static_cast<double>(1 / (i+1));

În primul rând, 1 / (i+1) obține evalua. Pentru că 1 este un int și i+1 este o int, astfel încât acesta este integer division, deci 1/(i+1) este o int. Rezultatul este apoi distribuit într-un double. Deci, din punct de vedere tehnic, static_cast<double>(1 / (i+1)); returnează un double, dar rezultatul este pierdut din cauza 1/(i+1) este integer division

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

Acum pentru static_cast<double>(i+1) este un dublu, 1 / static_cast<double>(i+1); este acum în virgulă mobilă divizie, astfel 1 / static_cast<double>(i+1); este un double

2021-11-21 13:26:20

Și, desigur, 1.0 /(i + 1) este chiar mai bine.
Pete Becker
1

Ar trebui să fie conștienți de Întreg Divizie

Puteți utiliza acest cod pentru a vedea, care de fapt revine o dublă. Cu toate acestea, ca urmare a împărțirii întregi, acesta va fi întotdeauna zero (sau 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;
}

Poți eluda împărțirii întregi, de nu împărțirea a două numere întregi. Pentru acestea este suficient dacă unul dintre ei este dublu.

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

Astfel încât să puteți vedea, este suficient pentru a arunca doar un sumand la dublu, în scopul de a transforma întreaga expresie într-o cameră dublă, care nu este întotdeauna zero.

2021-11-21 13:30:50

În alte limbi

Această pagină este în alte limbi

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