Jaka jest kolejność operacji rzutowania w arytmetyce w c++?

0

Pytanie

Dlaczego to

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

Zwrot int w C++ i dlaczego to

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

Zwrot double? W szczególności, dlaczego casting odbywa się po +-operacja, wystarczająca do uzyskania double. Dlaczego nie jest to wymagane do + lub też w liczniku? Jest static_cast preferowany sposób castingu?

Kod:

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

Najlepsza odpowiedź

2

Nie ma czegoś takiego jak "zasady rzutowania", bo typ wyrażenia zależy od jego operandów. Mówiąc prościej, jeśli binarny operator arytmetyczny przyjmuje dwa operandy różnych typów, to mniejszy typ będzie niejawnie przekształcony w szerszy typ

W result = static_cast<double>(1 / (i+1)) on analizowany w następujący sposób

  • i + 1 czy int wyrażenie, odkąd oba i i 1 należą do typu int
  • 1 / (i + 1) zwraca int z tego samego powodu
  • Wtedy wynik 1 / (i + 1) statycznie jest dostosowany do double

OD w result = 1 / (i+static_cast<double>(1)) tak

  • 1 rzuca się na double
  • i + static_cast<double>(1) ZWROT double bo i rzuca się na double z powodu drugiego operandu
  • 1 / (i+static_cast<double>(1)) to double wyraz z tego samego powodu

Ale nikt tak nie grał. Najlepiej to zrobić 1 / (i + 1.0) zamiast

Pełna zazwyczaj wygląda tak

  • Jeśli którykolwiek z operandów jest typu wyliczenia z obszarem działania, konwersja się nie powiedzie: inny argument i typ zwracanej wartości muszą mieć ten sam typ
  • W przeciwnym razie, jeśli którykolwiek z operandów jest long doubledrugi argument jest przekształcana w long double
  • W przeciwnym razie, jeśli którykolwiek z operandów jest doubledrugi argument jest przekształcana w double
  • W przeciwnym razie, jeśli którykolwiek z operandów jest floatdrugi argument jest przekształcana w float
  • W przeciwnym razie operand ma całkowitą typ (bo bool, char, char8_t, char16_t, char32_t, wchar_ti na tym etapie było продвинуто wyliczenie bez obszarze), i w celu uzyskania ogólnego typu stosuje się zintegrowane konwersji, jak pokazano poniżej:
    • Jeśli oba operandy są podpisane lub oba bez znaku, argument z mniejszym stopniem konwersji przekształca się w operand jest z dużą wartością całkowitą stopniem konwersji
    • W przeciwnym razie, jeśli stopień konwersji niepodpisanego operandu jest większy lub równy rzędowi konwersji podpisanego operandy, podpisany przez operand jest konwertowany na typ operandu bez znaku.
    • W przeciwnym razie, jeśli rodzaj podpisanej operandu może reprezentować wszystkie wartości operandu bez znaku, argument bez znaku przekształca się w rodzaj podpisanej operandy
    • W przeciwnym razie oba operandy są przekształcane w беззнаковый analog rodzaju podpisanej operandy.

Stopień konwersji powyżej wzrasta w kolejności bool, signed char, short, int, long, long long. Stopień dowolnego typu bez znaku jest równy rzędowi odpowiedniego typu ze znakiem. W rankingu char jest równy rzędowi signed char i unsigned char. Szeregi char8_t, char16_t, char32_ti wchar_t równe randze ich podstawowych typów.

Operatory arytmetyczne

2021-11-21 13:34:10

Świetnie, dziękuję! Jest to odpowiedź, której szukałem. Znalazłem sztuczka z 1.0 szczególnie przydatne!
DataFace
1
static_cast<double>(1 / (i+1));

Pierwszy, 1 / (i+1) otrzymasz ocenę. Bo 1 to int i i+1 czy inttak , że to całe dzielenie, więc 1/(i+1) czy int. Następnie wynik jest przekształcana w double. Więc technicznie, static_cast<double>(1 / (i+1)); zwraca a doubleale wynik jest stracone, bo 1/(i+1) jest wartością całkowitą podział

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

Teraz, bo static_cast<double>(i+1) jest podwójnym, 1 / static_cast<double>(i+1); teraz dzielenie zmiennopozycyjne, w ten sposób 1 / static_cast<double>(i+1); to double

2021-11-21 13:26:20

I, oczywiście, 1.0 /(i + 1) to nawet lepiej.
Pete Becker
1

Musisz wiedzieć o podziale целочисленном

Można użyć ten kod, aby zobaczyć, że naprawdę zwraca podwójne znaczenie. Jednak ze względu na podziale całkowitej ono zawsze będzie równa zero (lub 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;
}

Można obejść int dzielenie, nie dzieląc dwie liczby całkowite. Aby to zrobić, wystarczy, jeśli jeden z nich jest sobowtórem.

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

W ten sposób można zobaczyć, że wystarczy to tylko jeden termin do podwójnego, aby włączyć wszystkie wyrażenie w podwójne, która nie zawsze jest równa zero.

2021-11-21 13:30:50

W innych językach

Ta strona jest w innych językach

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