it-swarm.com.de

Ist es in Sprachen, die keine Unterstriche in ganzzahligen Konstanten zulassen, eine gute Praxis, eine Konstante für 1 Milliarde zu erstellen?

Ist es in Sprachen, die keine Unterstriche in ganzzahligen Literalen zulassen, eine gute Idee, eine Konstante für 1 Milliarde zu erstellen? z.B. in C++:

size_t ONE_BILLION = 1000000000;

Natürlich sollten wir keine Konstanten für kleine Zahlen wie 100 erstellen. Aber mit 9 Nullen ist es wohl einfach, eine Null wegzulassen oder eine zusätzliche Eins in Code wie diesen einzufügen:

tv_sec = timeInNanosec / 1000000000;
tv_nsec = timeInNanosec % 1000000000;
39

Die meisten Sprachen verfügen über eine Art Exponentialschreibweise. Eine Million ist 1e6 (Was 1 mal 10 hoch 6 bedeutet). Dies löst das Problem im Grunde noch besser als die meisten Vorschläge hier.

In vielen C-ähnlichen Sprachen definiert die wissenschaftliche Notation jedoch eine Gleitkommatyp, was bedauerlich ist, wenn Sie wirklich ein int benötigen. Sie können diese Konstante jedoch leicht tippen, um implizite Konvertierungen in Ihrem Formular zu vermeiden.

n / int(1e9) würde durch eine Milliarde teilen.

In Ihrem Beispiel, das sich mit physikalischen Größen (Zeit in Nanosekunden) befasst, würde ich mich im Allgemeinen fragen, ob eine Ganzzahl der richtige Typ ist. Tatsächlich ist ein Gleitkomma double möglicherweise besser geeignet, wenn messbare Größen verwendet werden (obwohl es natürlich Fälle gibt, in denen Sie einen long long Bevorzugen möchten).

33
wirrbel

Erstellen Sie stattdessen eine mit dem Namen NANOSECONDS_IN_ONE_SECOND als das, was sie darstellt.

Oder ein kürzerer, besserer Name, wenn Sie sich einen vorstellen können.

145
JohnB

Konstanten sollen Zahlen Bedeutung geben. Es gibt keine zusätzliche Bedeutung in ONE_BILLION bis 1000000000. Tatsächlich macht es das verwirrender, weil in verschiedenen natürlichen Sprachen eine Milliarde etwas anderes bedeutet (entweder tausend Millionen oder eine Million Millionen)! Wenn Sie es kürzer schreiben möchten, besteht eine gute Chance, dass Ihre Programmiersprache die Verwendung der wissenschaftlichen Notation zulässt, d. H. 1e9. Ansonsten stimme ich @JohnB zu, dass diese Zahl wirklich die Anzahl der Nanosekunden in einer Sekunde bedeutet. Nennen Sie es also so.

67
Thijs van Dien

Für ein oder zwei Verwendungen würde ich die Konvention verwenden:

tv_sec = timeInNanosec / (1000 * 1000 * 1000);
tv_nsec = timeInNanosec % (1000 * 1000 * 1000);

Es ist vollkommen selbsterklärend, wird zu einer Konstanten kompiliert und ist schwer zu vermasseln.

Es ist auch sehr nützlich in Fällen wie:

var Time = 24 * 60 * 60;

wo es leicht zu sehen ist, sprechen wir über einen Tag in Sekunden.

27
Sklivvz

Die Länge des Wertes definiert nicht, ob eine Konstante benötigt wird oder nicht.

Sie verwenden Konstanten, um magische Zahlen zu vermeiden, nicht um das Tippen zu vermeiden.

Zum Beispiel sind dies vollkommen gültige Konstanten:

public static final int CLOSE_CURSORS_AT_COMMIT = 1;
public static final int CONCUR_READ_ONLY = 2;
public static final int CONCUR_UPDATABLE = 3;
public static final int FETCH_FORWARD = 4;
public static final int FETCH_REVERSE = 5; 
public static final int FETCH_UNKNOWN = 6;
public static final int HOLD_CURSORS_OVER_COMMIT = 7;
public static final int TYPE_FORWARD_ONLY = 8;
public static final int TYPE_SCROLL_INSENSITIVE = 9;
public static final int TYPE_SCROLL_SENSITIVE = 10;

Verwenden:

public static final int NANOSECS_PER_SECOND = 1000000000;

(Codebeispiele sind in Java, in Ihre Lieblingssprache übersetzen)

10

Eine amerikanische oder europäische Milliarde?

(oder technisch gesehen eine Milliarde im kurzen oder langen Maßstab - einer ist 1000 Millionen, der andere ist eine Million Millionen).

Angesichts dieser Verwirrung würde ich ja sagen - es ist sinnvoll, es einmal zu definieren und dabei zu bleiben. Dies gilt auch für jede Konstante, auf die Sie sich einigen müssen - definieren Sie es einmal.

8
gbjbaanb

Gründe, dies nicht zu tun

Erstens gibt es hier einen Grund, keine Unterstriche zu schreiben oder einen Trick zu verwenden, um dies zu simulieren: Es macht es schwieriger, die Konstanten im Code zu finden. Angenommen, ein Programm weist irgendwo in seinem Betrieb einen fest codierten Wert 1500000 für einen Parameter auf. Ich möchte wissen, wo im Quellcode des Programms dies tatsächlich vorkommt, also greife ich nach dem Code für 1500000 Und finde nichts. Warum? Könnte es hexadezimal sein (aber warum für eine so runde Dezimalzahl). Ohne mein Wissen wird die Konstante tatsächlich als 1_500_000 Geschrieben. Ich brauchte den regulären Ausdruck 1_?500_?000.

Leitfiguren im Kommentar

Nur weil eine Art von visueller Hilfe nicht verfügbar ist oder wir sie aus dem oben genannten Grund nicht verwenden möchten, bedeutet dies nicht, dass wir die beiden Dimensionen der Textdatei nicht nutzen können, um eine alternative visuelle Hilfe zu erstellen:

foo = bar / 1000000000;
//           --^--^--^  

Damit können wir uns leicht davon überzeugen, dass es drei Gruppen von drei Nullen gibt. Trotzdem können wir den Quellcode für 1000000000 Suchen und finden.

Syntaxfärbung

Ein Texteditor mit programmierbarer Syntaxfärbung kann zur besseren Lesbarkeit für Farbgruppenziffern in numerischen Konstanten mit alternierenden Farben erstellt werden. Wir müssen im Code nichts tun.

Vorverarbeitung: C, C++, Ziel C.

Wenn wir wirklich Kommas zwischen Ziffern wollen, können wir in C und C++ eine Vorverarbeitung verwenden:

/* Four digit base TH-ousand constant macro */
/* Condensed using Horner's rule */
#define TH(A,B,C,D) ((((((A) * 1000) + (B)) * 1000) + (C)) * 1000 + D)

tv_sec = nanoseconds / TH(1,000,000,000)

Funktioniert für Zahlen wie TH(1,234,567,890).

Ein Makro ähnlich TH kann auch mit Token-Einfügen anstelle von Arithmetik arbeiten. Im C-Präprozessor kann der binäre Operator ## ("Token-Einfügen") in einem Makro verwendet werden body, um zwei Operanden zu einem einzigen Token zusammenzufügen. Einer oder beide Operanden können Makroargumente sein. Der Nachteil hier (was für uns ein Risiko darstellt) ist, dass das Verhalten so ist, wenn die resultierende Verkettung kein gültiges Token ist nicht definiert.

#define TOK4(A, B, C, D) A ## B ## C ## D

Jetzt

TOK4(1,000,000,000)       /* produces the single token 1000000000 */
TOK4(1,123,000,000.0E+2)  /* produces the single token 1123000000.0E+2 */
TOK4(pr,in,t,f)           /* produces the token printf */
TOK4(#,*,a,b)             /* undefined behavior, #*ab is not valid token syntax */

C-Programme, die Bezeichner zusammenfügen und die Ergebnisse zur Benennung globaler Variablen und Funktionen verwenden, existieren und sind schrecklich zu bearbeiten, da sie für Tools wie GNU id-utils und ctags undurchlässig sind).

5
Kaz

Im Allgemeinen ist es eine schlechte Idee, skalare Konstanten für Einheitenumrechnungen zu verwenden. Wenn Sie Konstanten für solche Dinge erstellen, führen Sie die Umrechnung an viel zu vielen Stellen durch.

Wenn Sie eine Menge von einer Einheit haben (z. B. 10 Sekunden) und in eine andere Einheit konvertieren möchten (d. H. Nanosekunden); Dies ist genau der richtige Zeitpunkt, um das Typsystem Ihrer Sprache zu verwenden, um sicherzustellen, dass die Einheiten tatsächlich so skaliert werden, wie Sie es beabsichtigen.

Lassen Sie Ihre Funktion einen Nanoseconds -Parameter verwenden und Konvertierungsoperatoren und/oder Konstruktoren in dieser Klasse für Seconds, Minutes oder what-have-you bereitstellen. Hier ist dein const int oder #define oder 1e9 in anderen Antworten gesehen gehört.

Dadurch wird vermieden, dass Variablen mit mehrdeutigen Einheiten in Ihrem Code schweben. und verhindert, dass ganze Schwaden von Fehlern auftreten, bei denen die falsche Multiplikation/Division angewendet wurde oder bereits angewendet wurde oder die Menge tatsächlich Entfernung statt Zeit war oder ...

In solchen Klassen ist es auch gut, die Konstruktion aus einfachen Skalaren privat zu machen und ein statisches "MakeSeconds (int)" oder ähnliches zu verwenden, um die schlampige Verwendung undurchsichtiger Zahlen zu verhindern.

Genauer gesagt zu Ihrem Beispiel in C++ check out Boost.Chrono .

3
rvalue

Ja, das klingt nach einer vernünftigen Idee. Off-by-One-DIGIT-Fehler sind noch schlimmer als die berüchtigten Off-by-One-Fehler. Es kann jedoch zu Verwirrung bei anderen Personen (einschließlich Ihres zukünftigen Selbst) führen, wenn Sie den Code lesen.

Ein erklärenderer Name wie NANOSEC_PER_SEC scheint gut zu sein, da er Klarheit darüber schaffen würde, wo er für die Zeit verwendet wird. Es macht jedoch keinen Sinn, in anderen Kontexten als der Zeit zu verwenden, und es wäre unpraktisch, für jede Situation eine separate 1.000.000.000 zu erstellen.

Was Sie wirklich tun wollen, albern, wie es auf den ersten Blick scheint, ist "Teilen über Sekunden". Dadurch bleibt NANO_PER erhalten, das nicht nur sprachunabhängig ist (10 ^ 9 in Amerika und Europa), sondern auch situationsunabhängig ist (keine Beschränkung der Einheiten) und einfach zu tippen und zu lesen ist.

3
MegaWidget

Ich persönlich würde es nicht als gute Praxis betrachten, eine Konstante zu erstellen, es sei denn, es muss eine Konstante sein. Wenn es sich an mehreren Stellen befindet und es oben in der Datei zum Ändern/Testen definiert wird, ist dies absolut nützlich.

Wenn es nur ist, weil es umständlich zu tippen ist? dann nein.

Wenn ich persönlich den Code eines anderen habe, für den eine Konstante definiert wurde, halte ich dies im Allgemeinen für einen wichtigen Aspekt des Codes. Z.B. TCP Keep Alive Timer, maximal zulässige Anzahl von Verbindungen. Wenn ich es debuggen müsste, würde ich wahrscheinlich viel unnötige Aufmerksamkeit darauf richten, um herauszufinden, warum/wo es verwendet wird.

1

Erstellen Sie keine Konstante für Ihre großen Literale. Sie würden für jedes solche Literal eine Konstante benötigen, was (meiner Meinung nach) ein kompletter Witz ist. Wenn Sie Ihre Literale unbedingt klarer machen müssen, ohne die Syntaxhervorhebung zu verwenden, können Sie (obwohl ich dies nicht tun würde) Funktionen oder Makros erstellen, um Ihr Leben "einfacher" zu machen:

#define SPLIT3(x, y, z) x##y##z

int largeNumber1 = SPLIT3(123,456,789);
int largeNumber2 = 123456789;
0
Thomas Eding

Wenn Sie darüber nachdenken, warum Sie in Ihrem Fragentitel "1 Milliarde" anstelle von "1000000000" geschrieben haben, werden Sie feststellen, warum die Antwort "Ja" lautet.

0
Alb

Ich würde das tun:

const int Million = 1000 * 1000;
const int Billion = 1000 * Million;

oder

const int SciMega = 1000 * 1000; const int SciGiga = 1000 * SciMega;

In Bezug auf die Anzahl der Nanosekunden pro Sekunde: Nano ist das "Inverse" von Giga.

Kilo  Mega  Giga   etc.
10^3  10^6  10^9
Milli Micro Nano   etc.
10^-3 10^-6 10^-9

Beachten Sie die "Sci" - für wissenschaftliche, wie in Computern, sind die Bedeutungen von Kilo, Mega, Giga usw. unterschiedlich: 1024 (2 ^ 10), 1024 * 1024 (2 ^ 20) usw. 2 Megabyte sind nicht 2.000.000 Bytes .

[~ # ~] update [~ # ~] Der Kommentator wies darauf hin, dass für digitale Exponenten von 2: http: //) spezielle Begriffe existieren en.wikipedia.org/wiki/Mebibyte

0
Mr. TA