Wie feststellen in C, ob Zahl grade oder ungrade?

#4234746
Lesenswert?

./. schrieb:
>> Dividieren
>
> Wohl kaum.

1 mod 2 = 1
2 mod 2 = 0
3 mod 2 = 1
4 mod 2 = 0

Doch, also das ist ziemlich einfach zum schreiben und (für mich) 
verständlicher als obige Bitmanipulation. Dass es wahrscheinlich länger 
zum ausführen braucht sollte bei einem PC-Programm bei solchem Kleinkram 
eher weniger Probleme machen.
Persönliche Seite #4234751
Lesenswert?

Jan H. schrieb:
> Dass es wahrscheinlich länger zum ausführen braucht

Tut es nur bei einem wirklich herausragend lausigen C-Compiler. Jeder 
andere erkennt, worum es bei % 2 geht.

Was ist eigentlich "einfacher" daran,
1
  a % 2
anstelle von
1
  a & 1
zu schreiben?

Die gleiche Anzahl von Zeichen, und beide Male ist das Sonderzeichen nur 
mit der Shifttaste erreichbar.
Gast #4234765
Lesenswert?

Jan H. schrieb:
> Mir liegt es näher, eine mathematische Eigenschaft mit einer
> mathematischen Funktion zu prüfen, statt mit einer, die auf einem
> Zahlensystem basiert. Ist aber persönliche Vorliebe.

So ein Quatsch. Beides basiert auf den Eigenschaften des 
zugrundeliegenden Zahlensystems. Das "2er" = bitoperation System deckt 
die binäre Eigenschaft "gerade/ungerade" besser ab als das Zehnersystem.
#4234818
Lesenswert?

A. K. schrieb:
> Der dividiert nämlich bei dessen meistgenutzer Optimierungsstufe -Os.
> Weil kürzer.

PS: Das bezog sich auf AVR.
1
int f(int a)
2
{
3
        return a % 2;
4
}

% bei -O1:
1
        andi r18,1
2
        andi r19,128
3
        tst r19
4
        brge .L2
5
        subi r18,1
6
        sbc r19,__zero_reg__
7
        ori r18,254
8
        ori r19,255
9
        subi r18,-1
10
        sbci r19,-1
11
.L2:

% bei -Os:
1
        ldi r22,lo8(2)
2
        ldi r23,0
3
        rcall __divmodhi4

& bei -Os/-O1:
1
        andi r18,1
2
        clr r19
#4234843
Lesenswert?

1
int_fast8_t iseven(int_fast8_t a)
2
{
3
  return (((a) / 2)*2 == (a));
4
}
5

6

7
#define ISEVEN(a) (((a) / 2)*2 == (a))
8

9

10
int main(void)
11
{
12
    % ... viel anderer Kram
13
    int8_t a = MCUCSR, b1, b2;
14
    b1 = iseven(a);
15
    b2 = ISEVEN(a);
16
    printf("b1=%i,b2=%i",b1,b2);
17

18

19
}

ergibt:
[a]
  int8_t a = MCUCSR, b1, b2;
    3f4e:  84 b7         in  r24, 0x34  ; 52



int_fast8_t iseven(int_fast8_t a)
{
  return (((a) / 2)*2 == (a));
    3f50:  28 2f         mov  r18, r24
    3f52:  87 ff         sbrs  r24, 7
    3f54:  02 c0         rjmp  .+4        ; 0x3f5a <main+0x38>
    3f56:  21 e0         ldi  r18, 0x01  ; 1
    3f58:  28 0f         add  r18, r24
    3f5a:  25 95         asr  r18
    3f5c:  22 0f         add  r18, r18
    3f5e:  33 0b         sbc  r19, r19
    3f60:  99 27         eor  r25, r25
    3f62:  87 fd         sbrc  r24, 7
    3f64:  90 95         com  r25
    3f66:  41 e0         ldi  r20, 0x01  ; 1
    3f68:  50 e0         ldi  r21, 0x00  ; 0
    3f6a:  28 17         cp  r18, r24
    3f6c:  39 07         cpc  r19, r25
    3f6e:  09 f0         breq  .+2        ; 0x3f72 <main+0x50>
    3f70:  40 e0         ldi  r20, 0x00  ; 0
    encoder_init();     // Drehgeber

  int8_t a = MCUCSR, b1, b2;
  b1 = iseven(a);
  b2 = ISEVEN(a);
  printf("b1=%i,b2=%i",b1,b2);
    3f72:  5f 93         push  r21
    3f74:  4f 93         push  r20
    3f76:  5f 93         push  r21
    3f78:  4f 93         push  r20
    3f7a:  8e ee         ldi  r24, 0xEE  ; 238
    3f7c:  90 e0         ldi  r25, 0x00  ; 0
    3f7e:  9f 93         push  r25
    3f80:  8f 93         push  r24
    3f82:  0e 94 35 20   call  0x406a  ; 0x406a <printf>
[/a]

bei -Os. Sehr interessant die sehr unterschiedliche Optimierung.
Gast #4234845
Lesenswert?

A. K. schrieb:
> Der Compiler berücksichtigt bei solchen Entscheidungen nur die Länge des
> unmittelbar erzeugten Codes, nicht die Länge von dadurch herangezogenen
> Laufzeitfunktionen.

Sorry, aber das verstehe ich jetzt nicht ganz. Heißt das, daß eine 
aufgerufene Funktion mit z.B. 500 Zeilen Code vom Compiler als kürzer 
angesehen wird, weil die eigentliche Funktion gar nicht mitgezählt wird, 
sondern nur der Aufruf dieser Funktion?
Da hab ich bestimmt einen Denkfehler, aber ich habe deine Aussage so 
verstanden. Korrigiere mich bitte!
#4234847
Lesenswert?

Michael B. schrieb:
> Erschreckend, daß Compiler immer noch genau so strohdoof sind wie vor 30
> Jahren (Optimierungsanalyse war meine Studienarbeit), aber grossmäulig
> ständig mit angeblichen superneuen Spitzenoptimierungen angepriesen
> werden.

Sehr erschreckend, dass jemand, der Optimierungsanalyse als 
Studienarbeit hatte, nicht erkennt, dass Optimierung auf Platz das Ziel 
hat, kürzeren Code zu erzeugen. Wenn der Aufruf der Laufzeitfunktion 
erheblich kürzer ist, dann ist das in diesem Sinn legitim.
Gast #4234853
Lesenswert?

gerade schrieb:
> Jan H. schrieb:
>> Mir liegt es näher, eine mathematische Eigenschaft mit einer
>> mathematischen Funktion zu prüfen, statt mit einer, die auf einem
>> Zahlensystem basiert. Ist aber persönliche Vorliebe.
>
> So ein Quatsch. Beides basiert auf den Eigenschaften des
> zugrundeliegenden Zahlensystems.

Und dann versuch mal, binäre Operationen auf floating Point anzusetzen. 
In modernen Sprachen ist nicht klar, daß Zahlen Integer sind.

Einfach hinschreiben, was man wirklich meint, und dann klapts in jeder 
Sprache. Geht natürlich der Coolnessfaktor "ich weiß wie das Teil innen 
funktioniert" verloren.

MfG Klaus
#4234855
Lesenswert?

?!? schrieb:
> Da hab ich bestimmt einen Denkfehler, aber ich habe deine Aussage so
> verstanden. Korrigiere mich bitte!

Richtig erfasst. Nur weiss der Compiler an der Stelle, an der diese 
Optimierung durchgeführt wird, nicht, wie gross die Laufzeitfunktion ist 
und auch nicht, wie oft sie aufgerufen wird. Wird diese int/int Division 
im gesamten Programm nur einmal verwendet, dann ist die Bilanz 
ungünstig. Wird sie 1000x aufgerufen, dann liegt er aber sowas von 
richtig.
#4234861
Lesenswert?

Michael B. schrieb:
> Erschreckend, daß Compiler immer noch genau so strohdoof sind wie vor 30
> Jahren (Optimierungsanalyse war meine Studienarbeit), aber grossmäulig
> ständig mit angeblichen superneuen Spitzenoptimierungen angepriesen
> werden.

Anderer Test, anderer Code ;-)
1
int f(int a, int b, int c)
2
{
3
        if (a % 2)
4
                return b;
5
        else
6
                return c;
7
}

mit -Os:
1
        mov r25,r23
2
        sbrc r24,0
3
        rjmp .L2
4
        mov r22,r20
5
        mov r25,r21
6
.L2:
7
        mov r24,r22

Es hängt schon ein wenig vom Kontext ab, was für Code produziert wird. 
Ganz so blöd ist GCC nämlich auch wieder nicht. Bei meinem Testcode oben 
hatte er keine Chance. Das hättest du als erklärter Kenner von Compilern 
eigentlich erkennen müssen.
Moderator #4234898
Lesenswert?

Klaus schrieb:
> Einfach hinschreiben, was man wirklich meint, und dann klapts in jeder
> Sprache.

Eben.

Ausnahmen bestätigen zwar die Regel, aber das sind dann meist
kompliziertere Fälle.

Im konkreten Beispiel klappt es jedenfalls ohne Verrenkungen:

1
#include <stdbool.h>
2

3
bool odd(int x) {
4
  return x % 2 != 0;
5
}

Der AVR-GCC liefert bei -O1, -O2, -O3 oder -Os:
1
odd:
2
  andi r24,lo8(1)
3
  ret
Gast #4235058
Lesenswert?

Jan H. schrieb:
> Mir liegt es näher, eine mathematische Eigenschaft mit einer
> mathematischen Funktion zu prüfen, statt mit einer, die auf einem
> Zahlensystem basiert. Ist aber persönliche Vorliebe.

Das kann aber beim Programmieren total in die Irre führen. Mathematisch 
ist es korrekt (und zeitgemäss) zu fragen, ob die Zahl zur Menge der 
geraden oder zur Menge der ungeraden Zahlen gehört. Blöd nur, dass beide 
Mengen unendlich sind (was einen Mathematiker überhaupt nicht stört, 
einen Computer aber schon).

Georg
Gast #4235177
Lesenswert?

Rolf M. schrieb:
> Du schreibst in beiden Fällen nicht hin, was du meinst.

Die Modulo-Methode nutzt aber eine mathematische Eigenschaft der geraden 
Zahlen und ist damit deutlich näher an der eigentlichen Fragestellung 
als die Bit-Anguck-Methode, die die Art, in der Zahlen im Speicher 
repräsentiert werden, ausnutzt und die Frage nur implizit beantwortet.
#4235192
Lesenswert?

Tom schrieb:
> als die Bit-Anguck-Methode, die die Art, in der Zahlen im Speicher
> repräsentiert werden, ausnutzt und die Frage nur implizit beantwortet.

Sollte jemand mal auf die mittlerweile recht exotische Idee kommen, 
Integers im Einerkomplement darzustellen, wird er die Bitvariante bei 
negativen Werten nicht nutzen können. Es gab aber eine Zeit, da war 
diese Darstellung nicht unüblich.
#4235249
Lesenswert?

ZehUndUnd schrieb:
> Der Funktionsname 'isnoteven' dürfte aussagekräftiger sein.

Die Funktionsnamen sind sowieso ein interessanter Punkt. Als alter 
Matlab-Nutzer wären mir als erstes die Namen "isodd"/"iseven" 
eingefallen. Oben fiel auch schon der Name "odd" - das klingt für mich 
deutlich C-mäßiger (da ein bischen kryptischer). Für den AVR wäre dann 
noch eine Funktion "oddi8" oder "oddu8" fällig. Von Funktionen, die nur 
direkt Flash-Konstanten unterstützen ("oddi8_P" und oddu8_P") würde ich 
allerdings absehen.

Der langen Scherze kurzer Sinn:

Wie würde ein langjähriger C-Veteran eine solche Funktion überhaupt 
nennen?
#4235254
Lesenswert?

Michael B. schrieb:
> Und warum erzeugt der Compiler dann nicht den
> Ist doch kurz, kürzer als alle beiden anderen.

Ist kurz aber falsch. -3 % 2 ist -1, nicht +1. Und bei aller Liebe zu 
Optimierung - es sollte schon das richtige Ergebnis rauskommen.

Mein Code verlangte nach dem Ergebnis von a % 2, Yalus aber nach dem von 
(a % 2) != 0. Das ist der entscheidende Unterschied, der bei Yalu dem 
Optimizer erlaubt, auf das Vorzeichen zu scheissen.
#4235284
Lesenswert?

Michael B. schrieb:
> Spielt, bei einer Auswertung durch if, aber keine Rolle, und das
> auszugucken sollte einen Compiler nicht überfordern.

Dummerweise war in meinem Code aber weit und breit kein "if" zu sehen.

Das war ein typischer Testcase einer einzelnen Operation. Minimiert auf 
die Essenz, isoliert in einer entsprechenden Funktion. Da hat der 
Compiler keinerlei Chance, irgendwas aus dem ihn nicht bekannten Kontext 
zu erschliessen.

Hintergrund: Shifts/Maskierungen werden ziemlich regelmässig als 
faktisch äquivalent zu div/mod mit Zweierpotenz gesehen. Das ist so 
verbreitet, dass es manche dann erstaunt, wenn es dank möglicher 
negativer Werte nicht so ist und es dann je nach Kontext und 
Zielmaschine böse Laufzeitauswirkung hat (arm-gcc verhält sich anders).

Die Methode, Eigenschaften in einzelne Zwergfunktionen auszulagern, ist 
nicht ganz so exotisch. Teils eine Stilfrage ist das bei C++ sehr 
verbreitet, und nicht immer inlined.
#4235295
Lesenswert?

Walter T. schrieb:
> Die Funktionsnamen sind sowieso ein interessanter Punkt. Als alter
> Matlab-Nutzer wären mir als erstes die Namen "isodd"/"iseven"
> eingefallen. Oben fiel auch schon der Name "odd" - das klingt für mich
> deutlich C-mäßiger (da ein bischen kryptischer). Für den AVR wäre dann
> noch eine Funktion "oddi8" oder "oddu8" fällig. Von Funktionen, die nur
> direkt Flash-Konstanten unterstützen ("oddi8_P" und oddu8_P") würde ich
> allerdings absehen.
>
> Der langen Scherze kurzer Sinn:
>
> Wie würde ein langjähriger C-Veteran eine solche Funktion überhaupt
> nennen?

Auf jeden Fall nicht iseven oder isodd, da diese Namen verboten sind.
Gast #4235347
Lesenswert?

A. K. schrieb:
> ZehUndUnd schrieb:
>> D. h. man muss die Forumspfeifen mit Diot anreden?
>
> Da Warenzeichen auf Produktbereiche bezogen sind, wär das nur der Fall,
> wenn Apple das auch für den Bereich von (geistiger) Gesundheit
> angemeldet hat, oder eine Verwechselbarkeit mit der eigenen kundschaft
> nicht auszuschlissen ist.

Ist aus deinen Ausführungen u. U. ein kleiner Vorbehalt gegenüber Apple 
herauszulesen?
Gast #4235349
Lesenswert?

Bei allem Tanz um den Namen: Ich nehme also eine Integerzahl, 
konvertiere sie in Text und prüfe ob die letzte Ziffer eine '1' ist.
"%i" formatiert Integer als eine ganz normale Dezimalzahl. Wo ist also 
die Prüfung auf 3, 5, 7 und 9? Nich sind 40% aller Ergebnisse falsch!
Gast #4235366
Lesenswert?

POSIX reserviert einige Namen, damit gewisse Bibliotheksfunktionen 
erweitert werden können. Damit es z.B. keine Kollisionen mit den 
Funktionen in ctype.h (isalpha,isdigit usw) gibt, sollen z.B. keine 
Namen mit "is" beginnen. Diese Einschränkung gibt es bei ISO-C selbst 
m.W. nicht.
#4235377
Lesenswert?

marco schrieb:
> Diese Einschränkung gibt es bei ISO-C selbst m.W. nicht.

Doch. Die kommt eigentlich da her.

Rufus Τ. F. schrieb:
> Im Draft für C-99 tauchen weder isodd noch iseven auf, und das sieht im
> Draft für C-11 (N1570) nicht anders aus.

Das liegt daran, daß es nicht explizit um diese Identifier geht, sondern 
um alle, die mit "is" gefolgt von einem Kleinbuchstaben anfangen. Diese 
sind reserviert für zukünftige Erweiterungen der Standardbibliothek. Das 
gilt übrigens nicht nur für Namen, die mit "is" anfangen, sondern auch 
für "to" und "str".
Zu finden ist das in C99 im Kapitel 7.26 "Future library directions".
Gast #4235399
Lesenswert?

Jan H. schrieb:
> Mir liegt es näher, eine mathematische Eigenschaft mit einer
> mathematischen Funktion zu prüfen, statt mit einer, die auf einem
> Zahlensystem basiert. Ist aber persönliche Vorliebe.

Ja. Persönliche Vorlieben zählen gelegentlich mehr als der Rest der 
Welt.

Der eigentliche Punkt ist jedoch ein wenig anders. Wir haben es hier 
definitionsgemäß mit Integerzahlen zu tun, oder versuchst du gar, einer 
Gleitkommazahl eine Eigenschaft Gerade/Ungerade zuzuordnen? 2.0000 ist 
gerade, 1.99999999999987 ist dann was? oder 1.23456789E68 ? Und wo soll 
die Grenze sein?

Also.
Wir haben Integerzahlen.
Basta.
Dort hat ein jedes Bit eine festgelegte Wertigkeit und eines dieser Bits 
hat die Wertigkeit 2^0, also 1. Für die Eigenschaft Gerade oder Ungerade 
ist das Prüfen genau dieses Bits das eigentliche Kriterium. Das Gerede 
von "Prüfung mit mathematischen Funktionen" ist in diesem Lichte nur 
Gebabbel.

W.S.
Gast #4235434
Lesenswert?

W.S. schrieb:

> Dort hat ein jedes Bit eine festgelegte Wertigkeit und
> eines dieser Bits hat die Wertigkeit 2^0, also 1. Für
> die Eigenschaft Gerade oder Ungerade ist das Prüfen
> genau dieses Bits das eigentliche Kriterium.

Ahh ja.

(-2 mod 2) ist in der üblichen Standard-Mathematik gleich
Null; mithin ist -2 gerade. Nachlesbar in jedem Mathe-Buch.

Bitte erläutere, wie das mit der Prüfung des LSB korrespondiert,
wenn auf der gewählten Plattform Integerzahlen in Einerkomplement-
darstellung (!!) codiert sind.

Vielen Dank im Voraus.
#4235440
Lesenswert?

Bastler schrieb:
> Wo ist also
> die Prüfung auf 3, 5, 7 und 9? Nich sind 40% aller Ergebnisse falsch!

Das macht nichts. In 90% aller unit-Tests würde die Funktion bestehen. 
Es würde getestet auf 0, 1, -1 und 32768.


Rolf M. schrieb:
> Das liegt daran, daß es nicht explizit um diese Identifier geht, sondern
> um alle, die mit "is" gefolgt von einem Kleinbuchstaben anfangen. Diese
> sind reserviert für zukünftige Erweiterungen der Standardbibliothek. Das
> gilt übrigens nicht nur für Namen, die mit "is" anfangen, sondern auch
> für "to" und "str".
> Zu finden ist das in C99 im Kapitel 7.26 "Future library directions".

Solche interessanten Schnipsel sind der Grund, warum ich auch 
sinnlos-Diskussionen so gerne weiterverfolge. Ich hätte eine derartige 
Funktion (von der Implementierung mal abgesehen) vermutlich tatsächlich 
je nach Tageslaune "iseven" oder "isEven" genannt.
#4235448
Lesenswert?

A. K. schrieb:
> Dummerweise war in meinem Code aber weit und breit kein "if" zu sehen.

Dummerweise bist du nicht das Mass aller Dinge. Gefragt war nach dem 
bool'schen Ergebnis ob eine Zahl gerade oder ungerade ist. Da ist eine 
-1 oder 1 als Ergebnis in C vollkommen egal. Ausserdem weiss der 
Compiler welche Zahl mod ist, nämlich 2, und kennt den Typ der 
hingehenden Zahl, das könnte ja unsigned sein.

Wie man's dreht und wendet, alle sind klüger als du.
Persönliche Seite #4235517
Lesenswert?

Walter T. schrieb:
> Wie würde ein langjähriger C-Veteran eine solche Funktion überhaupt
> nennen?
1
fast_int8_t fast_int8_t_promoted_to_int_equals_fast_int8_t_promoted_to_int_divided_by_two_multiplied_by_two_as_fast_int8_t (fast_int8_t a)
2
{
3
    return (a / 2) * 2 == a;
4
}

Viel besser ist aber die Umsetzung von
a in Z ist gerade  <==>  a in 2·Z  <==>  existiert k in Z so dass a = 2 
* k.

Hier also die ultimative Lösung (C99):
1
#include <stdbool.h>
2
#include <limits.h>
3

4
bool iseven (int a)
5
{
6
    bool even = false;
7
    int k = INT_MIN;
8

9
    while (true)
10
    {
11
        // Avoid C's undefined behavior on signed overflow!
12
        // Only perform 2 * k if it won't overflow.
13
        if (k >= INT_MIN / 2 && k <= INT_MAX / 2)
14
            if (a == 2 * k)
15
                even = true;
16
        if (k == INT_MAX)
17
            break;
18
        else
19
            k++;
20
    }
21

22
    return even;
23
}

...damit unsere Compiler-Optimatoren wie Michael ein bisschen was zu 
kniffeln haben.

Wenn deine Optimierungen dann "a & 1" liefern, dann bist du *echt* gut!
Gast #4235540
Lesenswert?

Rolf M. schrieb:

> Klaus schrieb:
>> Einfach hinschreiben, was man wirklich meint, und dann
>> klapts in jeder Sprache.
>
> Du schreibst in beiden Fällen nicht hin, was du meinst.

Doch.

Gerade Zahlen sind, wenn mich die Reste meiner Mathekenntnisse
nicht trügen, so definiert, dass sie bei Division durch 2 den
Rest Null lassen ( = sich ohne Rest teilen lassen).

In Zeichen: N mod 2 = 0.
Gast #4235546
Lesenswert?

... schrieb:

>> wenn auf der gewählten Plattform Integerzahlen in
>> Einerkomplementdarstellung (!!) codiert sind.
>
> Einerkomplement ist heute praktisch irrelefant.

Dein Einwand ist irrelevant. Du hast das Problem nicht
verstanden.

"mod" basiert direkt auf der DEFINITION der geraden
Zahl und muss damit auf jeder Plattform und mit jeder
beliebigen internen Darstellung von Ganzzahlen korrekt
funktionieren.

Die Lösung mit "&" hängt von der internen Zahldarstellung
ab.
Persönliche Seite #4235583
Lesenswert?

Possetitjel schrieb:
> Die Lösung mit "&" hängt von der internen Zahldarstellung ab.

Und woher bitte hast du dieses "Wissen"?

§ 6.2.6 Representations of types

§ 6.2.6.1 General

.3 Values stored in unsigned bit-fields and objects of type unsigned 
char shall be represented using a pure binary notation. *)

*) A positional representation for integers that uses the binary digits 
0 and 1, in which the values represented by successive bits are 
additive, begin with 1, and are multiplied by successive integral powers 
of 2, except perhaps the bit with the highest position. (Adapted from 
the American National Dictionary for Information Processing Systems.) A 
byte contains CHAR_BIT bits, and the values of type unsigned char range 
from 0 to 2^CHAR_BIT - 1.

§ 6.2.6.2 Integer types

.1 For unsigned integer types other than unsigned char, the bits of the 
object representation shall be divided into two groups: value bits and 
padding bits (there need not be any of the latter). If there are N value 
bits, each bit shall represent a different power of 2 between 1 and 
2^{N-1}, so that objects of that type shall be capable of representing 
values from 0 to 2^N - 1 using a pure binary representation; this shall 
be known as the value representation. The values of any padding bits are 
unspecified.
Moderator #4235632
Lesenswert?

Johann L. schrieb:
> Possetitjel schrieb:
>> Die Lösung mit "&" hängt von der internen Zahldarstellung ab.
>
> Und woher bitte hast du dieses "Wissen"?
>
> § 6.2.6 Representations of types
>
> § 6.2.6.1 General
>
> .3 Values stored in unsigned bit-fields and objects of type unsigned
> char shall be represented using a pure binary notation. […]
>
> § 6.2.6.2 Integer types
>
> .1 For unsigned integer types other than unsigned char, […]

Das n & 1 liefert zwar für nichtnegative Werte das gewünschte Ergebnis,
nicht aber für negative Werte in Einerkomplementdarstellung. n % 2 != 0
hingegen funktioniert immer.

Hier sind übrigens noch zwei weitere, funktional angehauchte Einzeiler
für odd und even (welches ich aus ästhetischen Gründen in evn umbenannt
habe):

1
bool odd(int n);
2

3
bool evn(int n) { return n == 0 || odd(n + (n<0) - (n>0)); }
4

5
bool odd(int n) { return n != 0 && evn(n + (n<0) - (n>0)); }

Auch diese Funktionen vermag der GCC nicht auf eine oder zwei Assembler-
Instruktionen zu reduzieren, aber immerhin löst er (mit -O2) die
Rekursion auf, so dass auch bei großen Argumenten kein Stack-Überlauf
entsteht.
Gast #4235634
Lesenswert?

Georg schrieb:

> Possetitjel schrieb:
>> Die Lösung mit "&" hängt von der internen Zahldarstellung
>> ab.
>
> Bitte nenne uns eine Integer-Darstellung, bei der das
> geringstwertige Bit NICHT die Wertigkeit 2^0 hat.
>
> Und das möglichst ohne endloses Rumgelabere.

Falls Du vorhast, es demnächst mal mit Höflichkeit zu
versuchen, können wir uns unterhalten.

Tschüss bis dahin.
Gast #4235636
Lesenswert?

Johann L. schrieb:
>> Die Lösung mit "&" hängt von der internen Zahldarstellung ab.
>
> Und woher bitte hast du dieses "Wissen"?

Dass das immer funktioniert, ist gar nicht die Frage.

Der Unterschied besteht darin, ob man sich innerhalb der 
Abstraktionsebene des eigentlichen Problems bewegt:
  "Zahl ist gerade, wenn Zahl mod 2 gleich Null ist."

Oder ob man die Frage, die auf der "mathematischen" Ebene (ganze Zahlen) 
angeordnet ist, beantwortet, indem man einen Umweg über die tiefere 
Ebene der internen Zahldarstellung geht:
  "Zahl ist gerade, wenn [hier gedanklich eine Ebene tiefer schalten
  in den Bereich der Bits] die letzte Stelle der binären Darstellung
  0 ist."

Ob man diesen Ebenunterschied überhaupt versteht/wahrnimmt, und, falls 
ja, ob man das abstraktionsebenenübergreifende Programmieren als 
unnötige Komplexität oder als natürlich empfindet, ist von Person zu 
Person sehr verschieden.


Grüße aus dem Elfenbeinturm ;)
Gast #4235638
Lesenswert?

Tom schrieb:

> Johann L. schrieb:
>>> Die Lösung mit "&" hängt von der internen Zahldarstellung
>>> ab.
>>
>> Und woher bitte hast du dieses "Wissen"?
>
> Dass das immer funktioniert, ist gar nicht die Frage.

Häh?
Sagt mal, Leute, LEST ihr manchmal auch, worum's geht?

Weiter oben ging es darum, dass man bei

--> NEGATIVEN <--

Zahlen, die in

--> EINERKOMPLEMENT-DARSTELLUNG <--

vorliegen, NICHT durch verUNDen bestimmen kann, ob die Zahl gerade
ist oder nicht. ES FUNKIONIERT NICHT! ES KOMMT DAS FALSCHE HERAUS!

"+2" sieht irgendwie so aus: "...000010"
"-2" sieht im Einerkomplement so aus: "...111101"

Klingelt's?
Gast #4235696
Lesenswert?

Nur mal eine Frage nebenbei: Wird die Einerkomplement-Darstellung 
überhaupt irgendwo angewendet?

Eine Darstellung, die zwei Darstellungen der Zahl "0" hat (-0 und +0) 
und wo bei Rechenoperationen, die über die 0-Grenze hinweggehen, das 
Ergebnis falsch ist und nur durch anschließende Addition von 1 
richtiggestellt wird.

Wird das irgendwo angewendet, oder ist das lediglich eine theoretische 
Darstellungsmöglichkeit?
Gast #4235698
Lesenswert?

Possetitjel schrieb:
> Weiter oben ging es darum, dass man bei
>
> --> NEGATIVEN <--
>
> Zahlen, die in
>
> --> EINERKOMPLEMENT-DARSTELLUNG <--
>
> vorliegen, NICHT durch verUNDen bestimmen kann, ob die Zahl gerade
> ist oder nicht. ES FUNKIONIERT NICHT! ES KOMMT DAS FALSCHE HERAUS!
unterschreib

Aber ist sinnlos, die raffens net mit ihrer Mikrooptimierung.

Premature optimization is the root of all evil.
Schreib das hin, was du meinst. Nicht das, von dem du glaubst, dass es 
effizienter ist.
Gast #4235699
Lesenswert?

asd schrieb:
> Wird das irgendwo angewendet, oder ist das lediglich eine theoretische
> Darstellungsmöglichkeit?
UNIVAC... früher.

Aber solange das noch im Standard zulässig ist, kann man sich ja 
aussuchen, ob man diese beknackte Mikrooptimierung mit "&" macht oder ob 
man hinschreibt, was man tatsächlich meint.
Portabel ist halt nur letzeres.
#4235734
Lesenswert?

Johann L. schrieb:
> fast_int8_t_promoted_to_int_equals_fast_int8_t_promoted_to_int_divided_b 
y_two_multiplied_by_two_as_fast_int8_t

Hmmm.... ohne auto-Vervollständigen dürfte der Name ziemlich 
fehlerträchtig sein. Und wenn man alle Funktionen nach diesem Schema 
benennt, sind mit den ersten 32 Zeichen 
"fast_int8_t_promoted_to_int_equa" vermutlich viele Namenskonflikte zu 
erwarten. Dein Vorschlag erscheint mir deshalb praxisfern.
Moderator #4235750
Lesenswert?

Nase schrieb:
> asd schrieb:
>> Wird das irgendwo angewendet, oder ist das lediglich eine theoretische
>> Darstellungsmöglichkeit?
> UNIVAC... früher.

In den 60er Jahren gab es die Einerkomplementdarstellung noch in einigen
anderen Systeme, u.a. von CDC.

Aber auch heute gibt es sie noch, nämlich in den Servern ClearPath
Dorado 880/88E und 890/89E des Univac-Nachfolgers Unisys. Die Produktion
dieser Server soll aber Ende dieses Jahres eingestellt werden:

  http://www.computerworld.com.au/article/547767/unisys_phasing_decades-old_mainframe_processor_x86_chips/

Die Datentypen dieser Rechner umfassen übrigens 9 Bit (char), 18 Bit
(short), 36 Bit (int und long) und 72 Bit (long long).

Ich schätze, dass Unisys einen Vertreter mit großer Klappe im ISO-C
Konsortium sitzen hat(te), der die Unterstützung dieser unüblichen
Datenformate durchsetzte, ähnlich wie IBM einen hinschickte, der den
Rausschmiss der Trigraphs aus dem C-Standard verhinderte.
Gast #4235793
Lesenswert?

> "mod" basiert direkt auf der DEFINITION der geraden
> Zahl und muss damit auf jeder Plattform und mit jeder
> beliebigen internen Darstellung von Ganzzahlen korrekt
> funktionieren.

Da sch..ss ich doch drauf. Ich benutze schon lange keinen Abakus mehr.
Gast #4235826
Lesenswert?

Welch ein Drama! Große Teile der weltweiten C-Source-Bestände sind nicht 
UNIVAC kompatibel. Daß es die heute noch gibt, liegt nur daran, daß 
manche Firmen wohl noch COBOL-Programme haben, die sie nicht ersetzen 
können/wollen.
Für alle die das nicht wissen: das waren die Maschinen aus den Doris Day 
Filmen, die man vor 45 Jahren schon als alte Schinken Sonntags 
nachmittags sehen konnte.
Wann kommt der AVR in der 9-Bit-UNIVAC-Edition?
#4235831
Lesenswert?

Johann L. schrieb:
> Walter T. schrieb:
>> Wie würde ein langjähriger C-Veteran eine solche Funktion überhaupt
>> nennen?
>
1
> fast_int8_t 
2
> fast_int8_t_promoted_to_int_equals_fast_int8_t_promoted_to_int_divided_by_two_multiplied_by_two_as_fast_int8_t 
3
> (fast_int8_t a)
4
>

Mit Sicherheit nicht, weil C nach dem 31. Zeichen bei Funktionsnamen 
(und Variablen) nicht mehr unterscheidet.
Gast #4235866
Lesenswert?

Die Bedingung "mindestens 31 signifikante Zeichen" bedeutet aber nicht, 
das mehr nicht sein darf. GCC hat keine Beschränkung. Eventuell aber die 
BinUtils der entsprechenden Ziel-Hardware, denn daraus benutzt GCC 
zumindest den Linker.
Was von Namen unbegrenzter (2GB) Länge zu halten ist: je länger desto 
unlesbarer. Nur wenn man C++-Namensräume/Klassen per 
Names-Konkatenierung implementieren will, dann bekommt man solche eben.
Gast #4236035
Lesenswert?

Portabilität kann auch bedeuten: auf allen Plattformen, die GCc 
unterstützt. Ich käme eh aus anderen Gründen nicht auf die Idee, so 
lange Namen zu verwenden,
Und zur ursprünglichen Fragestellung: Ist es ein echtes Problem, wenn 
ich die "isOddOrNot"-Routine im Fall der Fälle auf "UNIVAC" anpassen 
muß. Ich würd's überleben, genau wie 99,999% aller 
"Nicht-Museums-Programmierer".
Gast #4236289
Lesenswert?

Jan H. schrieb:
> 4 mod 2 = 0
>
> Doch, also das ist ziemlich einfach zum schreiben und (für mich)
> verständlicher als obige Bitmanipulation.

Modulo ist aber relativ aufwändig zu rechnen, falls der von dir 
verwendete C-Compiler nicht auf den Spezialfall "Modulo 2" optimiert 
ist. Und du hattest nach der schnellsten Möglichkeit gefragt.

Oder meintest du damit, wo du am wenigsten nachdenken musst und das 
Programm deshalb schnell geschrieben ist?

richard schrieb:
> was ist wohl in C die einfachste bzw. schnellste Möglichkeit,
Gast #4236491
Lesenswert?

Echt?
Ich glaube es geht sogar ohne Hochsprache. Wie sollte die Maschine das 
auch anstellen, die kann nur Maschinenbefehle. Für sie, die Maschine, 
wurde Hochsprachen aber auch nicht erfunden, sondern um konkrete 
Probleme zu lösen. Und in 39-stellige Namen verschlüsselte 3..4 
Namespaces sind eher der Weisheit letzter Stuss.
Moderator #4236526
Lesenswert?

Rolf M. schrieb:
> Ich auch, aber es gibt Leute, die sowas ernsthaft machen.
> Siehe z.B.
> 
https://people.gnome.org/~shaunm/girdoc/C/Gtk.RadioMenuItem.new_with_mnemonic_from_widget.html

1
gtk_radio_menu_item_new_with_mnemonic_from_widget

Hui, das sind ja immerhin 49 Zeichen!

Und da es auch noch den Identifier
1
gtk_radio_menu_item_new_with_mnemonic

gibt, der mit dem obigen die ersten 37 Zeichen gemeinsam hat, können die
GTK-Entwickler ja froh sein, dass sich der GCC diesbezüglich nicht auf
die Mindestanforderung des C-Standards (31 Zeichen) beschränkt :)
Gast #4236610
Lesenswert?

Hallo,

Bastler schrieb:
> Echt?
> Ich glaube es geht sogar ohne Hochsprache. Wie sollte die Maschine das
> auch anstellen, die kann nur Maschinenbefehle. Für sie, die Maschine,
> wurde Hochsprachen aber auch nicht erfunden, sondern um konkrete
> Probleme zu lösen. Und in 39-stellige Namen verschlüsselte 3..4
> Namespaces sind eher der Weisheit letzter Stuss.

Da hast Du natürlich Recht. Der Weisheit allerletzter Stuss wäre es 
aber, bescheuerte Namensgebung als Argument gegen Sprachen, 
Sprachfamilien oder Paradigmen anführen zu wollen. Sowas liegt am 
Programmierer. ;-)

Liebe Grüße,
Karl
#4238111
Lesenswert?

Karl Käfer schrieb:
> Bastler schrieb:
>> Da kann man schön sehen, was passiert wenn OO doch "auch mit
>> prozeduralen Sprachen geht".
>
> Was nichts an der schlichten Tatsache ändert, daß es geht und
> offensichtlich auch in der Praxis benutzt wird.

Ich würde das eher umgekehrt formulieren. Es geht zwar und wird auch in 
der Praxis benutzt, ist aber trotzdem Mist. ;-)

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren