Błąd w koniunkcji - prawda && falsz && prawda -> prawda

0

Cześć,
jestem nowicjuszem i mam taki problem, ponieważ za zadanie miałem wyznaczyć pary liczb, w których zachodzi warunek:
a == sumaDzielnikow(b) && b == sumaDzielnikow(a) && a != b

Problem pojawia się w koniunkcji, konkretnie dla a=3, b=4 (i innych także) albowiem w moim programie widać, jakoby PRAWDA && FAŁSZ && PRAWDA miałoby mi dawać prawdę. Mam nadzieję, że program dokładniej wyjaśnia o co mi dokładnie chodzi:

#include <iostream>

using namespace std;

int sumaDzielnikow(int n) {
  int suma;
  for(int i=n-1; i>0; i--) {
      if(n%i==0)
          suma+=i;
  }
  return suma;
}

void przyjazn(int n) {

  for(int a=1; a<=n; ++a) {
      for(int b=n; b>0; --b) {
          if(a == sumaDzielnikow(b) && b == sumaDzielnikow(a) && a != b)
              cout << a << " i " << b << " sa zaprzyjaznione" << "    a: " << a << "   b: " << b << " suma dziel a= " << sumaDzielnikow(a) << "  suma dziel b=" << sumaDzielnikow(b) << endl;
          else
              cout << a << "   " << b << "    a: " << a << "   b: " << b << " suma dziel a= " << sumaDzielnikow(a) << "  suma dziel b=" << sumaDzielnikow(b) << endl;
  
      }
  
  }
}

int main()
{
    if ( 3 == sumaDzielnikow(4) && 4 == sumaDzielnikow(3) && 3 != 4)    // dlaczego prawda,fałsz,prawda to prawda???
        cout << "prawda";
    else
        cout << "falsz";


    if ( 4 == sumaDzielnikow(3) && 3 != 4)
        cout << "prawda";
    else
        cout << "falsz";

    cout << endl << 3 << "=?" << sumaDzielnikow(4) << endl << 4 << "=?" << sumaDzielnikow(3) << endl;

    przyjazn(4);
}
5

Po pierwsze:
int suma; Zmienna suma zawiera teraz jakieś śmiecie.

Po drugie:
if(x) cout<<"prawda"; else cout<<"falsz";
lepiej zastąpić na:
cout<<(x?"prawda":"falsz")<<endl;
lub przy deklaracji:

static const char *boolstr[]={"falsz","prawda"};
cout<<boolstr[x]<<endl;

Po trzecie:
zacznij od prostego for(int i=1;i<10;++i) cout<<i<<' '<<sumaDzielnikow(i)<<endl;

Po czwarte:
Warto dla 1 imperatywnie zwrócić 1,
Dla pozostałych wartości zacząć licznik od 1+n (bo się dzieli przez siebie i przez 1) i sprawdzać od 2 do pierwiastku z liczby (wyłącznie) dodając 2 bo się dzieli przez sprawdzaną oraz przez wynik liczba/sprawdzana oraz dodać 1 jeżeli pierwiastek zaokrąglony w dół też jest dzielnikiem.
Czyli coś na kształt:

unsigned long long SumOfDividers(unsigned long long n)
{
  if(n==1) return 1;
  unsigned long long sq=sqrt(n),count=1+n+(sq*sq==n?sq:0);
  while(sq-->1) count+=(n%sq?0:sq+n/sq);
  return count;
}
4

@nowy113:

Nie od rzeczy będzie przypomnieć (10 strona podręcznika), że wartościowanie koniunkcji && jest przerywane przy pierwszy false - trudno stawiać jakies domniemania jakie są kolejne elementy, bo nie są wartościowane

Alternatywy || odwrotnie

3

Włącz ostrzeżenia kompilatora, a nawet traktuj je jako błędy: https://godbolt.org/z/35znz1Yac
Kompilator od razu wskazuje problem.

  • jak używasz gcc/clang, to trzeba dodać flagi kompilacji: -Wall -Wextra -Werror
  • jak używasz MSVC (VIsualStudio), to trzeba dodać flagi kompilacji: /W4 /WX

Zalecam też używać flag sanitizera na gcc/clang: -fsanitize=address,undefined podczas testowania aplikacji. Dodany zostanie kod sprawdzający w trakcie najważniejsze błędy programistyczne. Raporty mogą wyglądać strasznie skomplikowanie na pierwszy rzut oka, ale wtedy wróć do nas i na bieżąco będziemy ci je tłumaczyć.

1 użytkowników online, w tym zalogowanych: 0, gości: 1