forked from Lehona/Ikarus
-
Notifications
You must be signed in to change notification settings - Fork 0
/
float_ohneIkarus.d
706 lines (572 loc) · 21.6 KB
/
float_ohneIkarus.d
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
//#################################################################
//
// 32 bit IEEE 754 floats (kurz: Gleitkommazahlen) für Daedalus:
// Script vom 26.11.2008, erstellt von Sektenspinner
//
// Es wird NICHT der vollständige IEEE 754 Standard unterstützt
// Es gibt Unterschiede in Spezialfällen und Rundungsfehler.
// Das grundsätzliche Format wird aber eingehalten, sodass
// auch mit Engine-Floats gerechnet werden kann.
//
// Bugfix am 19.03.2010:
// Grober Fehler: Exponent war stets um eins falsch.
// Das fiel auf, da durch die neue "Forschung" auch
// "externe floats" aus der Engine aus den Scripten
// erreichbar sind.
// Bugfix am 1.07.2010:
// Grober Fehler: mulf lieferte stets positive Ergebnisse
// Danke an orcwarriorPL!
// Bugfix am 23.09.2010:
// Behoben sind:
// -Problem in truncf bei sehr kleinen Zahlen
// -Problem in addf falls Exponenten sich um
// mehr als 31 unterscheiden.
// -Subtraktion von zwei gleichen Zahlen ergibt nun
// null (anstatt ~2^(-23) mal diese Zahl)
// -Die Funktionen sollten nun beliebig schachtelbar sein.
// Danke an mud-freak!
// Erweiterung am 5.2.2011:
// -fracf hinzugefügt, danke an orcwarriorPL!
// Erweiterung am 7.4.2011:
// -sqrtf_approx hinzugefügt, geschrieben von Lehona
// Performanceverbesserung 8.4.2011:
// -sqrtf beschleunigt, Dank gebührt Lehona
//
//#################################################################
/*####################################
// Kurzdokumentation
//####################################
//*********************
// Grundsätzliches
//*********************
32-bit Floats der Genauigkeit "single" werden mit den in diesem Script enthaltenen Funktionen auf einem gewöhnlichen integer simuliert. Dabei ist darauf zu achten floats und integer trotz des formal gleichen Datentyps penibel zu unterscheiden. Wenn eine Zahl in Floatdarstellung mit einer Zahl in Integerdarstellung verrechnet wird oder Funktionen auf integer angewendet werden, die eigentlich für floats gedacht sind oder umgekehrt kommt im besten Fall einfach nur Blödsinn heraus. Normalerweise meckert in so einem Fall der Compiler, Gothic kennt aber den Unterschied nicht!
//************************************
// Das Instrumentarium
//************************************
Um mit floats rechnen zu können, müssen diese zunächst erzeugt werden. Dazu gibt es eine Abbildung mkf, die eine integer Ganzzahl in einen float umwandelt.
floats können untereinander addiert, subtrahiert, multipliziert und dividiert werden. Eine Wurzelfunktion ist ebenfalls definiert.
Um den Wert der floats intepretieren zu können, sind die Ordnungsrelationen >=, >, <, <= mit den Funktionen ge, g, l, le gegeben.
Ferner können floats mit der truncf und roundf Funktion zurück in einen integer konvertiert werden.
//************************************
// Die Funktionen im Überblick:
//************************************
"func float" und "var float" wie hier angegeben gibt es nicht wirklich (für Gothic sind alles integer). Diese Notation soll hier nur zur Veranschaulichung dienen.
Um sich die Funktionsnamen merken zu können hilft vielleicht folgende Liste, die die Abkürzungen erklärt:
mkf = make float
truncf = truncate float
roundf = round float
addf = add floats
subf = subtract floats
negf = negate float
mulf = multiply floats
divf = divide floats
invf = inverse float
gf = greater
gef = greater or equal
lf = lower
lef = lower or equal
sqrtf = square root of float
printf = print float
**************** Umwandlung *******************
func float mkf (var int x) //Erzeugt die Floatdarstellung aus einer Ganzzahl.
func int truncf (var float x) //reduziert einen float auf seinen Ganzzahlanteil, wobei alle Nachkommastellen verworfen werden. Der Ergebnistyp ist Integer. (-1.5 würde zu -1.0, nicht zu -2)
func int roundf (var float x) //reduziert einen float auf eine Ganzzahl, die durch Runden ermittelt wird. Wie truncf, nur das zuvor 0.5 addiert wird. Der Ergebnistyp ist Integer.
**************** Addition *********************
func float addf (var float x, var float y) //addiert x und y und gibt das Ergebnis zurück.
func float subf (var float x, var float y) //subtrahiert y von x und gibt das Ergebnis zurück.
func float negf (var float x) //Gibt das additive Inverse von x (also -x) zurück.
**************** Multiplikation ***************
func float mulf (var float x, var float y) //multipliziert x und y miteinander und gibt das Ergebnis zurück.
func float divf (var float x, var float y) //dividiert x durch y und gibt das Ergebnis zurück.
func float invf (var float x) //Gibt das multiplikative Inverse des floats x, also 1/x zurück. Gibt für x = 0 einen Fehler aus.
func float fracf (var int p, var int p) //Gibt den Bruch p/q als float zurück. Äquivalent zu divf(mkf(p), mkf(q))
**************** Ordnungsrelationen ***********
func int gf (var float x, var float y) //gibt für x > y TRUE zurück, sonst FALSE
func int gef (var float x, var float y) //gibt für x >= y TRUE zurück, sonst FALSE
func int lef (var float x, var float y) //gibt für x <= y TRUE zurück, sonst FALSE
func int lf (var float x, var float y) //gibt für x < y TRUE zurück, sonst FALSE
**************** Verschiedene *****************
func float sqrtf (var float x) //gibt die Wurzel des floats x zurück. Gibt für negative x einen Fehler aus.
func float sqrtf_approx (var float x) //berechnet die Wurzel erheblich performanter als sqrtf aber möglicherweise ungenauer
func void printf (var float x) {}; //gibt einen float als Kommazahl auf dem Bildschirmaus. Diese Funktion funktioniert für sehr große und sehr kleine x nicht richtig.
//************************************
// Sonstiges
//************************************
Es sind fünf float Konstanten definiert, die genutzt werden können, ohne dass sie erst berechnet/erzeugt werden müssen:
FLOATNULL = 0
FLOATEINS = 1
FLOATHALB = 0.5
PI = 3.1415...
E = 2.7182...
//************************************
// Beispiele
//************************************
Folgende Funktion soll das Volumen eines Zylinders in cm³ berechnen und gerundet zurückgeben:
func int Zylindervolumen (var int radius, var int hoehe) {
var int radiusf, var int hoehef;
radiusf = mkf (radius);
hoehef = mkf (hoehe);
//Volumen = r² * PI * h
var int ergebnisf;
ergebnisf = mulf (radiusf, radiusf);
ergebnisf = mulf (ergebnisf, PI);
ergebnisf = mulf (ergebnisf, h);
return roundf (ergebnisf);
};
Folgende Funktion berechnet eine Zahl und gibt sie auf dem Bildschirm aus. Sie schachtelt dabei manche Funktionen
func void antwort () {
var int foo;
foo = mulf (mkf (1337), PI);
printf (divf (foo, mkf (100)));
//(1337*PI)/100 ist verblüffend genau 42. ;-)
};
Folgende Funktion macht ein paar Vergleiche. Es wird in keinem Fall "FEHLER" ausgegeben.
func void floattest()
{
var int halb; var int eins; var int zwei;
var int null;
var int minuseins; var int minuszwei;
halb = invf (mkf (2));
eins = mkf (1);
zwei = mkf (2);
null = mkf (0);
minuseins = mkf (-1);
minuszwei = mkf (-2);
if (gf (zwei,eins)) {} else { print ("FEHLER!"); };
if (gf (eins,null)) {} else { print ("FEHLER!"); };
if (lf (minuseins,null)) {} else { print ("FEHLER!"); };
if (lf (minuszwei,minuseins)) {} else { print ("FEHLER!"); };
if (gf (halb,minuseins)) {} else { print ("FEHLER!"); };
if (lf (halb,zwei)) {} else { print ("FEHLER!"); };
if (lef (null,null)) {} else { print ("FEHLER!"); };
if (gef (null,null)) {} else { print ("FEHLER!"); };
};
//************************************
// Beschränkungen und Fallen
//************************************
*********** Nutzerfehler ************
Es sollten unter keinen Umständen die Operatoren +, -, * oder / auf floats angewendet werden. Sie haben dort keine sinnvolle Anwendung. Bestensfalls kommt einfach nur Blödsinn heraus. Wie oben beschrieben sind addf, subf, mulf und divf anzuwenden.
Wer versteht wie ein float intern aufgebaut ist, kann zum Beispiel innerhalb der positiven Zahlen die Ordnungsrealtionen (>, <, <= >=) benutzen. Wer sich nicht sicher ist, sollte auf die gegebenen Funktionen zurückgreifen.
Natürlich sind umgekehrt die Floatfunktionen für Integer unbrauchbar. Der Ausdruck sqrtf (4) ist nicht 2 sondern einfach nur falsch, da 81 ein Integer ist!
*********** Float-Fehler *************
Die Genauigkeit der floats ist sehr begrenzt, ab etwa 4 Dezimalstellen ist mit Rundungsfehlern zu rechnen. Dafür können sehr große und sehr kleine Zahlen dargestellt werden.
Es gelten die gewöhnlichen Einschränkungen und Empfehlungen für floats. Zum Beispiel ist es selten sinnvoll floats auf Gleichheit zu überprüfen, da es durch Rundungsfehler wahrscheinlich ist, dass auch zwei floats, die eigentlich gleich sein müssten kleine Abweichungen zueinander aufweisen. Es sollte in einem solchen Fall besser geprüft werden, ob die Differenz der beiden floats einen (im Verhältnis zur Problemstellung) kleinen Wert unterschreitet.
//************************************
// Vielen Dank...
//************************************
...dass du dich für dieses Script interessierst und es gelesen, oder zumindest überflogen hast. Dann war meine Arbeit nicht ganz umsonst. ;-)
Mir ist allerdings bewusst, dass dies wohl eher ein Randgebiet des Gothicmoddings ist.
Edit: März 2010: Haha! Mit direktem Zugriff auf zEngine Objekte ist dies mitnicht ein Randgebiet! Es lassen sich einige hochinteressante Floatwerte in Gothic finden!
*/
//#################################################################
//
// DIE FUNKTIONEN
//
//#################################################################
const int BIT_VZ = 1; //Vorzeichen hat 1 Bit (was auch sonst?!)
const int BIT_EXP = 8; //nach IEEE 754 ist 8 die Norm
const int BIT_MT = 23; //bleiben 23 bit für die Mantisse
const int EXP_OFFSET = 127; //exp = characteristic - EXP_OFFSET
const int EXP_PATTERN = ((1 << BIT_EXP) - 1) << BIT_MT;
const int MT_PATTERN = ((1 << BIT_MT) - 1);
const int MINUS = 1 << 31;
const int MININT = 1 << 31;
const int MAXINT = MININT - 1;
const int FLOATNULL = 0; //vz 0, exp -128, mt 1.0 //nicht echt 0! Aber so ziemlich. Damit die Vergleiche gut funktionieren. Letztendlich ist der Wert aber egal. FLOATNULL ist ein Symbol mit dem nicht gerechnet wird.
const int FLOATEINS = 1065353216; //vz 0, exp 0 (also 127), mt 1.0
const int FLOATHALB = 1056964608; //vz 0, exp -1 (also 126), mt 1.0
const int PI = 1078530011;
const int E = 1076754516;
//************************************
// Interne Hilfsfunktionen
//************************************
func int HighestBitPos (var int x) {
if (x == 0) {
return 0;
}
else {
return 1 + HighestBitPos (x >> 1);
};
};
func int extractExp (var int x) {
var int exp;
exp = x & EXP_PATTERN;
exp = exp >> BIT_MT;
exp = exp - EXP_OFFSET; //wegen Vergleichen ist der exponent verschoben
return exp;
};
func int extractMt (var int x) {
var int mt;
mt = x & MT_PATTERN;
//das erste bit, was gespart wurde wieder hin:
mt = mt | (1 << BIT_MT);
return mt;
};
func int packExp (var int exp) {
//exponent -> Charakteristik -> und schieben
return (exp + EXP_OFFSET) << BIT_MT;
};
//************************************
// float bauen:
//************************************
func int mkf (var int x) {
var int result; result = 0;
//das Vorzeichen bit
if (x < 0) {
result = MINUS;
x = -x;
};
var int exp;
exp = HighestBitPos (x) - 1;
if (exp < 0) { //kann nur heißen, dass die Zahl null ist
return FLOATNULL;
};
//Dass die erste Zahl eine 1 ist, ist ja wohl klar, also wird sie abgeschnitten:
x = x & (~(1 << exp));
//Und jetzt packe ich das ganze in einen float:
result = result | packExp(exp); //den Exponenten neben die Mantisse schieben.
if (BIT_MT > exp) {
return result | (x << (BIT_MT - exp)); //Die Mantisse wird nach vorne geschoben, aber eben nur soweit Platz ist
}
else {
return result | (x >> (exp - BIT_MT));
};
};
//************************************
// Rückumwandlung zu integer
//************************************
func int truncf (var int x) {
//Sonderbehandlung für das Symbol NULL
if (x == FLOATNULL) {
return 0;
};
var int exp; exp = extractExp (x); //Exponenten holen
var int mt; mt = extractMt (x); //Mantisse holen
var int result;
//Überläufe:
if (exp >= 31) { //2^31 * 1.0 läuft ins Vorzeichenbit rein!
if (x > 0) {
return MAXINT;
} else {
return MININT;
};
};
//schneidet
if (exp > BIT_MT) {
result = mt << (exp - BIT_MT); //Mantisse zurechtschieben
}
else {
//32 bit oder mehr schieben geht schief.
if (BIT_MT - exp > 31) {
return 0;
};
result = mt >> (BIT_MT - exp);
};
if (x < 0) {
return - result;
}
else {
return result + 0;
};
};
//************************************
// Addition
//************************************
func int addf (var int x, var int y) {
var int expX; expX = extractExp (x);
var int expY; expY = extractExp (y);
var int mtX; mtX = extractMt (x);
var int mtY; mtY = extractMt (y);
var int isnegX; isnegX = x & MINUS;
var int isnegY; isnegY = y & MINUS;
//Sonderbehandlung für das Symbol NULL
if (x == FLOATNULL) {
return y + 0;
}
else if (y == FLOATNULL) {
return x + 0;
};
//Die Betragsmäßig kleinere Zahl an die größere anpassen
if (expX > expY)
{
if (expX - expY > 31) {
//dann schlagen die folgenden shiftoperationen fehl.
//Aber x ist soviel größer als y, einfach x zurückgeben.
return x + 0;
};
mtY = mtY >> (expX - expY);
expY = expX;
}
else
{
if (expY - expX > 31) {
//dann schlagen die folgenden shiftoperationen fehl.
//Aber y ist soviel größer als x, einfach y zurückgeben.
return y + 0;
};
mtX = mtX >> (expY - expX);
expX = expY;
};
//Das Ergebnis berechnen:
var int mtRes;
if (isnegX) {
mtRes = -mtX;
}
else {
mtRes = mtX;
};
if (isnegY) {
mtRes -= mtY;
}
else {
mtRes += mtY;
};
var int isnegRes;
if (mtRes < 0) {
isnegRes = MINUS;
mtRes = -mtRes;
}
else {
isnegRes = 0;
};
//Präzisierung:
if (!mtRes) { //damit abziehen eines Wertes von sich selbst präzise ist.
return FLOATNULL;
};
var int shift;
shift = HighestBitPos (mtRes) - (BIT_MT + 1);
if (shift > 0) {
mtRes = mtRes >> shift;
}
else {
mtRes = mtRes << (-shift);
};
//Noch die erste Zahl abschneiden (also zuschneiden):
mtRes = mtRes & ((1 << BIT_MT) - 1);
var int expRes;
expRes = expX + shift;
return isnegRes | packExp(expRes) | mtRes;
};
//************************************
// Es lassen sich vier kleine
// nützliche Hilfsfunktionen
// definieren:
//************************************
func int negf (var int x) {
if (x < 0) { return x & (~MINUS); }
else { return x | MINUS; };
};
func int absf (var int x) {
if (x < 0) { return negf (x); }
else { return x + 0; };
};
func int subf (var int x, var int y) {
return addf (x, negf (y));
};
func int roundf (var int x) {
if (x < 0) {
return truncf (subf (x, FLOATHALB));
} else {
return truncf (addf (x, FLOATHALB));
};
};
//************************************
// Multiplikation
//************************************
func int mulf (var int x, var int y) {
var int expX; expX = extractExp (x);
var int expY; expY = extractExp (y);
var int mtX; mtX = extractMt (x);
var int mtY; mtY = extractMt (y);
var int isnegX; isnegX = x & MINUS;
var int isnegY; isnegY = y & MINUS;
//Sonderbehandlung für das Symbol NULL
if (x == FLOATNULL)
|| (y == FLOATNULL) {
return FLOATNULL;
};
//Die Exponenten werden addiert
var int expRes;
expRes = expX + expY;
//Die Mantissen multipliziert (wobei auf die 32 bit Grenze geachtet werden muss)
var int mtRes;
mtRes = (mtX >> (BIT_MT - 14)) * (mtY >> (BIT_MT - 14));
mtRes = mtRes >> (28 - BIT_MT);
if (mtRes >= (1 << (BIT_MT + 1)))
{
mtRes = mtRes >> 1;
expRes += 1;
};
//Noch die erste Zahl abschneiden (also die Mantisse zuschneiden):
mtRes = mtRes & ((1 << BIT_MT) - 1);
var int isNegRes;
if (isnegX == isnegY) {
isNegRes = 0;
}
else {
isNegRes = MINUS;
};
//noch Erkenntnisse zusammenfügen
return isnegRes | packExp(expRes) | mtRes;
};
//************************************
// Die Division lässt sich
// nicht auf die Multiplikation
// zurückführen. Das multiplikative
// Inverse ist schließlich schwerer
// zu finden, als das additive
// Inverse. Also, gesonderte Funktion:
//************************************
func int divf (var int x, var int y) {
var int expX; expX = extractExp (x);
var int expY; expY = extractExp (y);
var int mtX; mtX = extractMt (x);
var int mtY; mtY = extractMt (y);
var int isnegX; isnegX = x & MINUS;
var int isnegY; isnegY = y & MINUS;
//Sonderbehandlung für das Symbol NULL
if (y == FLOATNULL) {
Print ("### ERROR: DIVISION BY ZERO ###");
return FLOATNULL;
}
else if (x == FLOATNULL) {
return FLOATNULL;
};
//Exponent subtrahieren
var int expRes;
expRes = expX - expY;
//Die Mantissen dividieren, davor Divident und Divisor passend hinschieben
var int mtRes;
mtRes = (mtX << (7)) / (mtY >> 9); //X soweit es geht nach links, Y auf die Mitte
mtRes = mtRes << (BIT_MT - 7 - 9);
//Und das Ergebnis wieder zurückschieben
if (mtRes < (1 << (BIT_MT))) {
mtRes = mtRes << 1;
expRes -= 1;
};
//Noch die erste Zahl abschneiden (also die Mantisse zuschneiden):
mtRes = mtRes & ((1 << BIT_MT) - 1);
var int isNegRes;
if (isnegX == isnegY) {
isNegRes = 0;
}
else {
isNegRes = MINUS;
};
//noch Erkenntnisse zusammenfügen
return isnegRes | packExp(expRes) | mtRes;
};
//************************************
// Kleine Hilfsfunktion
//************************************
func int invf (var int x) {
return divf (FLOATEINS, x);
};
/* thanks to orcwarriorPL for the idea! */
func int fracf (var int p, var int q) {
return divf(mkf(p), mkf(q));
};
//************************************
// Wurzelziehen
//************************************
func int sqrtf_hlp (var int target, var int guess, var int steps) {
//babylonisches Wurzelziehen / Heron
guess = addf (guess, divf (target, guess));
guess = mulf (FLOATHALB, guess);
if (steps == 0) {
return guess;
} else {
return sqrtf_hlp (target, guess, steps - 1);
};
};
func int sqrtf (var int x) {
if (x < FLOATNULL) {
Print ("ERROR: sqrtf: x must be nonnegative.");
return FLOATNULL;
};
//guess wird der Startwert des Heronverfahrens
//der Exponent von guess soll der halbe Exponent von x sein.
var int e;
e = ExtractExp(x);
e = e/2;
var int guess;
guess = packExp(e); //Mantisse ist egal.
//4 ist schon eher viel. Man kann hier auch auf 3 runtergehen.
//ab 4 dürfte sich das Ergebnis spätestens stabilisiert haben.
return sqrtf_hlp (x, guess, 4) + 0;
};
//Schnelles Wurzelziehen von Lehona getreu dem Wikipedia Artikel:
// http://en.wikipedia.org/wiki/Fast_inverse_square_root
func int sqrtf_approx(var int f) {
var int x2f;
var int threehalfs;
if (!threehalfs) {
threehalfs = addf(FLOATEINS, FLOATHALB);
};
x2f = mulf(f, FLOATHALB);
f = 1597463007 /* 5F3759DFh */ - (f >> 1);
return invf(mulf(f, subf(threehalfs, mulf(x2f, mulf(f,f)))));
};
//************************************
// Ordnungsrelationen
//************************************
func int gf (var int x, var int y) {
var int isnegX; isnegX = x & MINUS;
var int isnegY; isnegY = y & MINUS;
if (isNegX && isNegY) { //beide negativ
if (x < y) {
return TRUE;
};
}
else {
if (x > y) {
return TRUE;
};
};
return FALSE;
};
func int gef (var int x, var int y) {
if (gf (x,y)) || (x == y) {
return TRUE;
};
return FALSE;
};
func int lef (var int x, var int y) {
if (!gf (x,y)) {
return TRUE;
};
return FALSE;
};
func int lf (var int x, var int y) {
if (!gef (x,y)) {
return TRUE;
};
return FALSE;
};
//************************************
// Ausgabefunktionen
//************************************
func string BuildNumberHlp (var string res, var int x, var int kommapos) {
if (kommapos == 0) {
res = ConcatStrings (",", res);
res = ConcatStrings (IntToString (x), res);
return res;
};
res = ConcatStrings (IntToString (x % 10), res);
return BuildNumberHlp (res, x / 10, kommapos - 1);
};
func string BuildNumber (var string res, var int x, var int kommapos) {
if (x < 0) {
return ConcatStrings ("-", BuildNumberHlp (res, -x, kommapos));
}
else {
return BuildNumberHlp (res, x, kommapos);
};
};
func void printf (var int x) { //Ok, ok sorry c-ler. Aber ich will konsistente Namen haben.
//Ich bekomme nur eine primitive Darstellung als Kommazahl hin.
//für die Darstellung als X * 10^EXP fehlen mir Ideen oder Logarithmusfunktionen
x = mulf (x, mkf (10000));
x = truncf (x);
Print (BuildNumber ("", x, 4));
};