2016-05-26 3 views
1

Ich habe ein Problem in einem Optimierungsschritt gebunden, die im Wesentlichen alsEin Wert wird nicht korrekt in einem Vektor

zusammengefasst werden können
auto s = v.size(); 

Wo v ein std::vector<double ist. (Im Wesentlichen ist dies ein Vektor, der eine symmetrische Funktion charakterisiert).

Ich habe dann einen Index i, der zwischen -s und +s sein muss. So verwende ich den folgenden Code:

if (i < -s || i > s) 

Aber das geht für niedrige Werte von i. Kann jemand etwas darüber sagen, warum das nicht funktioniert? Wenn es relevant ist, ist i vom Typ int.

+3

Wie kann ein Index negativ sein? – NathanOliver

+0

Das bezieht sich auf die symmetrische Natur der Funktion. Vertrau mir ;-) –

+0

Was ist der Typ von 'i'? –

Antwort

1

Mit Blick auf die Frage und einige Ihrer Kommentare, es scheint, dass Sie denken, dass auto tut etwas anderes.

Da C++ 11, dann ist es nicht mehr verwendet einfach ein Variable automatische Speicherdauer zu bezeichnen (wie beispielsweise static gegen), aber folgert auch die Typen aus der Sache, die es zugewiesen Wesen . (Beachten Sie aber, dass auto s in 11 Tagen vor C++ ein Syntaxfehler ist: Sie müssten den Typ explizit angeben).

So ist die Typ von s ist eigentlich std::vector<double>::size_type was ein unsigned Typ. Hier beginnt der Spaß.

Die Operation des unären Minus-Operators auf einem vorzeichenlosen Typ ist selbst vorzeichenlos. (Eigentlich so, dass -s + snur umschließt auf Null). Darüber hinaus bedeutet Typ Förderung von int zu unsigned dass Ausdrücke wie i < -s in unsigned Arithmetik ausgewertet werden.

Es sind diese Effekte, die die Verwirrung verursachen.

Wenn ich Sie wäre, würde ich die negativen Werte von i mit std::abs konvertieren.

Es gibt einige technische Begriffe in dieser Antwort; Ich habe kursiv geschrieben, die Sie weiter erforschen sollten.

+0

Danke bathsheba. das ist klar. und ich mag einige deiner anderen Antworten –

0

Versuchen, dies zu verstehen, was los ist:

#include <iostream> 
#include <vector> 
using namespace std; 

int main() { 
    vector<int> a{1}; 
    auto s = a.size(); 
    cout << -s; 
    return 0; 
} 

Was möchten Sie als Ergebnis sehen? Nicht -1, oder?

Also, ich glaube, Sie verwenden soll wie folgt:

auto s = static_cast<int>(v.size()); 

Nun, wenn Sie schreiben if (i < -s || i > s) Sie erwartete Ergebnis.

+0

Was zum Teufel? –

+0

Vielleicht sollte ich bei Fortran 90 bleiben! –

+0

@Puglia Wenn Sie das gleiche Verhalten in Fortan 90 sehen wollen, dann verwenden Sie int wie in 'auto s = static_cast (v.Size())' –

2

Ihr Problem hier ist -s gibt Ihnen nicht den umgekehrten Wert der Größe. s wird ein vorzeichenloser ganzzahliger Typ sein (höchstwahrscheinlich std::size_t). Da es nicht vorzeichenbehaftet ist, kann es nicht negativ sein, so dass -s unterfließt und maximum_value_s_can_hold - s wird.

Wenn Sie überprüfen möchten, ob ein Wert nicht innerhalb des Bereichs (-size, size) liegt, müssen Sie die Größe in einer vorzeichenbehafteten Integer-Variablen speichern. Wenn Sie wissen, wie hoch der wahrscheinliche Wertebereich ist, können Sie einen Datentyp verwenden, der diese Werte enthält. Ansonsten würde ich vorschlagen, dass Sie eine long long oder std::ptrdiff_t verwenden.

+0

Danke. Ich muss das unbedingt studieren! –

+0

@Puglia Kein Problem. Es bekommt eine Menge Leute. – NathanOliver

+0

Übrigens hat meine Kollegin gesagt, ich sollte auto int schreiben. –

0

Im folgenden

std::vector<T> v; 
auto s = v.size(); 

s als auto deklariert wird, das heißt, durch sie abgeleitet werden ist RHS. vector::size() kehrt vector::size_type, die

ist

Unsigned integral type (usually std::size_t)

Jetzt -s einen (leise) Unterlauf erzeugt; große Zahl fast sicher größer als jeder Index des Vektors.

Um zu überprüfen, ob die Zahl zwischen (-s, s) ist, haben Sie s unterzeichnet Typ zu konvertieren (vorzugsweise long long int, da es mindestens 64-Bits ist oder irgendwelchen von Fixed width integer types falls erforderlich).

Verwandte Themen