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
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
|
class_name Big
extends RefCounted
## Big number class for use in idle / incremental games and other games that needs very large numbers
##
## Can format large numbers using a variety of notation methods:[br]
## AA notation like AA, AB, AC etc.[br]
## Metric symbol notation k, m, G, T etc.[br]
## Metric name notation kilo, mega, giga, tera etc.[br]
## Long names like octo-vigin-tillion or millia-nongen-quin-vigin-tillion (based on work by Landon Curt Noll)[br]
## Scientic notation like 13e37 or 42e42[br]
## Long strings like 4200000000 or 13370000000000000000000000000000[br][br]
## Please note that this class has limited precision and does not fully support negative exponents[br]
## Big Number Mantissa
var mantissa: float
## Big Number Exponent
var exponent: int
## Metric Symbol Suffixes
const suffixes_metric_symbol: Dictionary = {
"0": "",
"1": "k",
"2": "M",
"3": "G",
"4": "T",
"5": "P",
"6": "E",
"7": "Z",
"8": "Y",
"9": "R",
"10": "Q",
}
## Metric Name Suffixes
const suffixes_metric_name: Dictionary = {
"0": "",
"1": "kilo",
"2": "mega",
"3": "giga",
"4": "tera",
"5": "peta",
"6": "exa",
"7": "zetta",
"8": "yotta",
"9": "ronna",
"10": "quetta",
}
# HACK: This dictionary is inefficient, along with toAA().
# Replace with better, ideally utilizing alphabet_aa system
## AA Suffixes
## @deprecated
static var suffixes_aa: Dictionary = {
"0": "",
"1": "k",
"2": "m",
"3": "b",
"4": "t",
"5": "aa",
"6": "ab",
"7": "ac",
"8": "ad",
"9": "ae",
"10": "af",
"11": "ag",
"12": "ah",
"13": "ai",
"14": "aj",
"15": "ak",
"16": "al",
"17": "am",
"18": "an",
"19": "ao",
"20": "ap",
"21": "aq",
"22": "ar",
"23": "as",
"24": "at",
"25": "au",
"26": "av",
"27": "aw",
"28": "ax",
"29": "ay",
"30": "az",
"31": "ba",
"32": "bb",
"33": "bc",
"34": "bd",
"35": "be",
"36": "bf",
"37": "bg",
"38": "bh",
"39": "bi",
"40": "bj",
"41": "bk",
"42": "bl",
"43": "bm",
"44": "bn",
"45": "bo",
"46": "bp",
"47": "bq",
"48": "br",
"49": "bs",
"50": "bt",
"51": "bu",
"52": "bv",
"53": "bw",
"54": "bx",
"55": "by",
"56": "bz",
"57": "ca"
}
## AA Alphabet
const alphabet_aa: Array[String] = [
"a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m",
"n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z"
]
## Latin Ones Prefixes
const latin_ones: Array[String] = [
"", "un", "duo", "tre", "quattuor", "quin", "sex", "septen", "octo", "novem"
]
## Latin Tens Prefixes
const latin_tens: Array[String] = [
"", "dec", "vigin", "trigin", "quadragin", "quinquagin", "sexagin", "septuagin", "octogin", "nonagin"
]
## Latin Hundreds Prefixes
const latin_hundreds: Array[String] = [
"", "cen", "duocen", "trecen", "quadringen", "quingen", "sescen", "septingen", "octingen", "nongen"
]
## Latin Special Prefixes
const latin_special: Array[String] = [
"", "mi", "bi", "tri", "quadri", "quin", "sex", "sept", "oct", "non"
]
## Various options to control the string presentation of Big Numbers
static var options = {
"dynamic_decimals": false,
"dynamic_numbers": 4,
"small_decimals": 3,
"thousand_decimals": 1,
"big_decimals": 1,
"scientific_decimals": 3,
"logarithmic_decimals": 4,
"thousand_separator": ",",
"decimal_separator": ".",
"suffix_separator": "",
"reading_separator": "",
"thousand_name": "thousand"
}
## Maximum Big Number Mantissa
const MANTISSA_MAX: float = 1209600.0
## Big Number Mantissa floating-point precision
const MANTISSA_PRECISION: float = 0.0000001
## int (signed 64-bit) minimum value
const INT_MIN: int = -9223372036854775808
## int (signed 64-bit) maximum value
const INT_MAX: int = 9223372036854775807
func _init(m: Variant = 1.0, e: int = 0) -> void:
if m is Big:
mantissa = m.mantissa
exponent = m.exponent
elif typeof(m) == TYPE_STRING:
var scientific: PackedStringArray = m.split("e")
mantissa = float(scientific[0])
exponent = int(scientific[1]) if scientific.size() > 1 else 0
else:
if typeof(m) != TYPE_INT and typeof(m) != TYPE_FLOAT:
printerr("Big Error: Unknown data type passed as a mantissa!")
mantissa = m
exponent = e
Big._sizeCheck(mantissa)
Big.normalize(self)
## Verifies (or converts) an argument into a Big number
static func _typeCheck(n) -> Big:
if n is Big:
return n
var result := Big.new(n)
return result
## Warns if Big number's mantissa exceeds max
static func _sizeCheck(m: float) -> void:
if m > MANTISSA_MAX:
printerr("Big Error: Mantissa \"" + str(m) + "\" exceeds MANTISSA_MAX. Use exponent or scientific notation")
## [url=https://en.wikipedia.org/wiki/Normalized_number]Normalize[/url] a Big number
static func normalize(big: Big) -> void:
# Store sign if negative
var is_negative := false
if big.mantissa < 0:
is_negative = true
big.mantissa *= -1
if big.mantissa < 1.0 or big.mantissa >= 10.0:
var diff: int = floor(log10(big.mantissa))
if diff > -10 and diff < 248:
var div = 10.0 ** diff
if div > MANTISSA_PRECISION:
big.mantissa /= div
big.exponent += diff
while big.exponent < 0:
big.mantissa *= 0.1
big.exponent += 1
while big.mantissa >= 10.0:
big.mantissa *= 0.1
big.exponent += 1
if big.mantissa == 0:
big.mantissa = 0.0
big.exponent = 0
big.mantissa = snapped(big.mantissa, MANTISSA_PRECISION)
# Return sign if negative
if (is_negative):
big.mantissa *= -1
## Returns the absolute value of a number in Big format
static func absolute(x) -> Big:
var result := Big.new(x)
result.mantissa = abs(result.mantissa)
return result
## Adds two numbers and returns the Big number result [br][br]
static func add(x, y) -> Big:
x = Big._typeCheck(x)
y = Big._typeCheck(y)
var result := Big.new(x)
var exp_diff: float = y.exponent - x.exponent
if exp_diff < 248.0:
var scaled_mantissa: float = y.mantissa * 10 ** exp_diff
result.mantissa = x.mantissa + scaled_mantissa
elif x.isLessThan(y): # When difference between values is too big, discard the smaller number
result.mantissa = y.mantissa
result.exponent = y.exponent
Big.normalize(result)
return result
## Subtracts two numbers and returns the Big number result
static func subtract(x, y) -> Big:
var negated_y := Big.new(-y.mantissa, y.exponent)
return add(negated_y, x)
## Multiplies two numbers and returns the Big number result
static func multiply(x, y) -> Big:
x = Big._typeCheck(x)
y = Big._typeCheck(y)
var result := Big.new()
var new_exponent: int = y.exponent + x.exponent
var new_mantissa: float = y.mantissa * x.mantissa
while new_mantissa >= 10.0:
new_mantissa /= 10.0
new_exponent += 1
result.mantissa = new_mantissa
result.exponent = new_exponent
Big.normalize(result)
return result
## Divides two numbers and returns the Big number result
static func divide(x, y) -> Big:
x = Big._typeCheck(x)
y = Big._typeCheck(y)
var result := Big.new(x)
if y.mantissa > -MANTISSA_PRECISION and y.mantissa < MANTISSA_PRECISION:
printerr("Big Error: Divide by zero or less than " + str(MANTISSA_PRECISION))
return x
var new_exponent = x.exponent - y.exponent
var new_mantissa = x.mantissa / y.mantissa
while new_mantissa > 0.0 and new_mantissa < 1.0:
new_mantissa *= 10.0
new_exponent -= 1
result.mantissa = new_mantissa
result.exponent = new_exponent
Big.normalize(result)
return result
## Raises a Big number to the nth power and returns the Big number result
static func power(x: Big, y) -> Big:
var result := Big.new(x)
if typeof(y) == TYPE_INT:
if y <= 0:
if y < 0:
printerr("Big Error: Negative exponents are not supported!")
result.mantissa = 1.0
result.exponent = 0
return result
var y_mantissa: float = 1.0
var y_exponent: int = 0
while y > 1:
Big.normalize(result)
if y % 2 == 0:
result.exponent *= 2
result.mantissa **= 2
y = y / 2
else:
y_mantissa = result.mantissa * y_mantissa
y_exponent = result.exponent + y_exponent
result.exponent *= 2
result.mantissa **= 2
y = (y - 1) / 2
result.exponent = y_exponent + result.exponent
result.mantissa = y_mantissa * result.mantissa
Big.normalize(result)
return result
elif typeof(y) == TYPE_FLOAT:
if result.mantissa == 0:
return result
# fast track
var temp: float = result.exponent * y
var newMantissa = result.mantissa ** y
if (round(y) == y
and temp <= INT_MAX
and temp >= INT_MIN
and is_finite(temp)
):
if is_finite(newMantissa):
result.mantissa = newMantissa
result.exponent = int(temp)
Big.normalize(result)
return result
# a bit slower, still supports floats
var newExponent: int = int(temp)
var residue: float = temp - newExponent
newMantissa = 10 ** (y * Big.log10(result.mantissa) + residue)
if newMantissa != INF and newMantissa != -INF:
result.mantissa = newMantissa
result.exponent = newExponent
Big.normalize(result)
return result
if round(y) != y:
printerr("Big Error: Power function does not support large floats, use integers!")
return power(x, int(y))
else:
printerr("Big Error: Unknown/unsupported data type passed as an exponent in power function!")
return x
## Square Roots a given Big number and returns the Big number result
static func root(x: Big) -> Big:
var result := Big.new(x)
if result.exponent % 2 == 0:
result.mantissa = sqrt(result.mantissa)
@warning_ignore("integer_division")
result.exponent = result.exponent / 2
else:
result.mantissa = sqrt(result.mantissa * 10)
@warning_ignore("integer_division")
result.exponent = (result.exponent - 1) / 2
Big.normalize(result)
return result
## Modulos a number and returns the Big number result
static func modulo(x, y) -> Big:
var result := Big.new(x.mantissa, x.exponent)
y = Big._typeCheck(y)
var big = { "mantissa": x.mantissa, "exponent": x.exponent }
Big.divide(result, y)
Big.roundDown(result)
Big.multiply(result, y)
Big.subtract(result, big)
result.mantissa = abs(result.mantissa)
return result
## Rounds down a Big number
static func roundDown(x: Big) -> Big:
if x.exponent == 0:
x.mantissa = floor(x.mantissa)
else:
var precision := 1.0
for i in range(min(8, x.exponent)):
precision /= 10.0
if precision < MANTISSA_PRECISION:
precision = MANTISSA_PRECISION
x.mantissa = floor(x.mantissa / precision) * precision
return x
## Equivalent of [code]min(Big, Big)[/code]
static func minValue(m, n) -> Big:
m = Big._typeCheck(m)
if m.isLessThan(n):
return m
else:
return n
## Equivalent of [code]max(Big, Big)[/code]
static func maxValue(m, n) -> Big:
m = Big._typeCheck(m)
if m.isGreaterThan(n):
return m
else:
return n
## Equivalent of [code]Big + n[/code]
func plus(n) -> Big:
return Big.add(self, n)
## Equivalent of [code]Big += n[/code]
func plusEquals(n) -> Big:
var new_value = Big.add(self, n)
mantissa = new_value.mantissa
exponent = new_value.exponent
return self
## Equivalent of [code]Big - n[/code]
func minus(n) -> Big:
return Big.subtract(self, n)
## Equivalent of [code]Big -= n[/code]
func minusEquals(n) -> Big:
var new_value: Big = Big.subtract(self, n)
mantissa = new_value.mantissa
exponent = new_value.exponent
return self
## Equivalent of [code]Big * n[/code]
func times(n) -> Big:
return Big.multiply(self, n)
## Equivalent of [code]Big *= n[/code]
func timesEquals(n) -> Big:
var new_value: Big = Big.multiply(self, n)
mantissa = new_value.mantissa
exponent = new_value.exponent
return self
## Equivalent of [code]Big / n[/code]
func dividedBy(n) -> Big:
return Big.divide(self, n)
## Equivalent of [code]Big /= n[/code]
func dividedByEquals(n) -> Big:
var new_value: Big = Big.divide(self, n)
mantissa = new_value.mantissa
exponent = new_value.exponent
return self
## Equivalent of [code]Big % n[/code]
func mod(n) -> Big:
return Big.modulo(self, n)
## Equivalent of [code]Big %= n[/code]
func modEquals(n) -> Big:
var new_value := Big.modulo(self, n)
mantissa = new_value.mantissa
exponent = new_value.exponent
return self
## Equivalent of [code]Big ** n[/code]
func toThePowerOf(n) -> Big:
return Big.power(self, n)
## Equivalent of [code]Big **= n[/code]
func toThePowerOfEquals(n) -> Big:
var new_value: Big = Big.power(self, n)
mantissa = new_value.mantissa
exponent = new_value.exponent
return self
## Equivalent of [code]sqrt(Big)[/code]
func squareRoot() -> Big:
var new_value := Big.root(self)
mantissa = new_value.mantissa
exponent = new_value.exponent
return self
## Equivalent of [code]Big == n[/code]
func isEqualTo(n) -> bool:
n = Big._typeCheck(n)
Big.normalize(n)
return n.exponent == exponent and is_equal_approx(n.mantissa, mantissa)
## Equivalent of [code]Big > n[/code]
func isGreaterThan(n) -> bool:
return !isLessThanOrEqualTo(n)
## Equivalent of [code]Big >== n[/code]
func isGreaterThanOrEqualTo(n) -> bool:
return !isLessThan(n)
## Equivalent of [code]Big < n[/code]
func isLessThan(n) -> bool:
n = Big._typeCheck(n)
Big.normalize(n)
if (mantissa == 0
and (n.mantissa > MANTISSA_PRECISION or mantissa < MANTISSA_PRECISION)
and n.mantissa == 0
):
return false
if exponent < n.exponent:
if exponent == n.exponent - 1 and mantissa > 10*n.mantissa:
return false #9*10^3 > 0.1*10^4
return true
elif exponent == n.exponent:
if mantissa < n.mantissa:
return true
return false
else:
if exponent == n.exponent + 1 and mantissa * 10 < n.mantissa:
return true
return false
## Equivalent of [code]Big <= n[/code]
func isLessThanOrEqualTo(n) -> bool:
n = Big._typeCheck(n)
Big.normalize(n)
if isLessThan(n):
return true
if n.exponent == exponent and is_equal_approx(n.mantissa, mantissa):
return true
return false
static func log10(x) -> float:
return log(x) * 0.4342944819032518
func absLog10() -> float:
return exponent + Big.log10(abs(mantissa))
func ln() -> float:
return 2.302585092994045 * logN(10)
func logN(base) -> float:
return (2.302585092994046 / log(base)) * (exponent + Big.log10(mantissa))
func pow10(value: int) -> void:
mantissa = 10 ** (value % 1)
exponent = int(value)
## Sets the Thousand name option
static func setThousandName(name: String) -> void:
options.thousand_name = name
## Sets the Thousand Separator option
static func setThousandSeparator(separator: String) -> void:
options.thousand_separator = separator
## Sets the Decimal Separator option
static func setDecimalSeparator(separator: String) -> void:
options.decimal_separator = separator
## Sets the Suffix Separator option
static func setSuffixSeparator(separator: String) -> void:
options.suffix_separator = separator
## Sets the Reading Separator option
static func setReadingSeparator(separator: String) -> void:
options.reading_separator = separator
## Sets the Dynamic Decimals option
static func setDynamicDecimals(d: bool) -> void:
options.dynamic_decimals = d
## Sets the Dynamic numbers digits option
static func setDynamicNumbers(d: int) -> void:
options.dynamic_numbers = d
## Sets the small decimal digits option
static func setSmallDecimals(d: int) -> void:
options.small_decimals = d
## Sets the thousand decimal digits option
static func setThousandDecimals(d: int) -> void:
options.thousand_decimals = d
## Sets the big decimal digits option
static func setBigDecimals(d: int) -> void:
options.big_decimals = d
## Sets the scientific notation decimal digits option
static func setScientificDecimals(d: int) -> void:
options.scientific_decimals = d
## Sets the logarithmic notation decimal digits option
static func setLogarithmicDecimals(d: int) -> void:
options.logarithmic_decimals = d
## Converts the Big Number into a string
func toString() -> String:
var mantissa_decimals := 0
if str(mantissa).find(".") >= 0:
mantissa_decimals = str(mantissa).split(".")[1].length()
if mantissa_decimals > exponent:
if exponent < 248:
return str(mantissa * 10 ** exponent)
else:
return toPlainScientific()
else:
var mantissa_string := str(mantissa).replace(".", "")
for _i in range(exponent-mantissa_decimals):
mantissa_string += "0"
return mantissa_string
## Converts the Big Number into a string (in plain Scientific format)
func toPlainScientific() -> String:
return str(mantissa) + "e" + str(exponent)
## Converts the Big Number into a string (in Scientific format)
func toScientific(no_decimals_on_small_values = false, force_decimals = false) -> String:
if exponent < 3:
var decimal_increments: float = 1 / (10 ** options.scientific_decimals / 10)
var value := str(snappedf(mantissa * 10 ** exponent, decimal_increments))
var split := value.split(".")
if no_decimals_on_small_values:
return split[0]
if split.size() > 1:
for i in range(options.logarithmic_decimals):
if split[1].length() < options.scientific_decimals:
split[1] += "0"
return split[0] + options.decimal_separator + split[1].substr(0,min(options.scientific_decimals, options.dynamic_numbers - split[0].length() if options.dynamic_decimals else options.scientific_decimals))
else:
return value
else:
var split := str(mantissa).split(".")
if split.size() == 1:
split.append("")
if force_decimals:
for i in range(options.scientific_decimals):
if split[1].length() < options.scientific_decimals:
split[1] += "0"
return split[0] + options.decimal_separator + split[1].substr(0,min(options.scientific_decimals, options.dynamic_numbers-1 - str(exponent).length() if options.dynamic_decimals else options.scientific_decimals)) + "e" + str(exponent)
## Converts the Big Number into a string (in Logarithmic format)
func toLogarithmic(no_decimals_on_small_values = false) -> String:
var decimal_increments: float = 1 / (10 ** options.logarithmic_decimals / 10)
if exponent < 3:
var value := str(snappedf(mantissa * 10 ** exponent, decimal_increments))
var split := value.split(".")
if no_decimals_on_small_values:
return split[0]
if split.size() > 1:
for i in range(options.logarithmic_decimals):
if split[1].length() < options.logarithmic_decimals:
split[1] += "0"
return split[0] + options.decimal_separator + split[1].substr(0,min(options.logarithmic_decimals, options.dynamic_numbers - split[0].length() if options.dynamic_decimals else options.logarithmic_decimals))
else:
return value
var dec := str(snappedf(abs(log(mantissa) / log(10) * 10), decimal_increments))
dec = dec.replace(".", "")
for i in range(options.logarithmic_decimals):
if dec.length() < options.logarithmic_decimals:
dec += "0"
var formated_exponent := formatExponent(exponent)
dec = dec.substr(0, min(options.logarithmic_decimals, options.dynamic_numbers - formated_exponent.length() if options.dynamic_decimals else options.logarithmic_decimals))
return "e" + formated_exponent + options.decimal_separator + dec
## Formats an exponent for string format
func formatExponent(value) -> String:
if value < 1000:
return str(value)
var string := str(value)
var string_mod := string.length() % 3
var output := ""
for i in range(0, string.length()):
if i != 0 and i % 3 == string_mod:
output += options.thousand_separator
output += string[i]
return output
## Converts the Big Number into a float
func toFloat() -> float:
return snappedf(float(str(mantissa) + "e" + str(exponent)),0.01)
func toPrefix(no_decimals_on_small_values = false, use_thousand_symbol=true, force_decimals=true, scientic_prefix=false) -> String:
var number: float = mantissa
if not scientic_prefix:
var hundreds = 1
for _i in range(exponent % 3):
hundreds *= 10
number *= hundreds
var split := str(number).split(".")
if split.size() == 1:
split.append("")
if force_decimals:
var max_decimals = max(max(options.small_decimals, options.thousand_decimals), options.big_decimals)
for i in range(max_decimals):
if split[1].length() < max_decimals:
split[1] += "0"
if no_decimals_on_small_values and exponent < 3:
return split[0]
elif exponent < 3:
if options.small_decimals == 0 or split[1] == "":
return split[0]
else:
return split[0] + options.decimal_separator + split[1].substr(0,min(options.small_decimals, options.dynamic_numbers - split[0].length() if options.dynamic_decimals else options.small_decimals))
elif exponent < 6:
if options.thousand_decimals == 0 or (split[1] == "" and use_thousand_symbol):
return split[0]
else:
if use_thousand_symbol: # when the prefix is supposed to be using with a K for thousand
for i in range(3):
if split[1].length() < 3:
split[1] += "0"
return split[0] + options.decimal_separator + split[1].substr(0,min(3, options.dynamic_numbers - split[0].length() if options.dynamic_decimals else 3))
else:
for i in range(3):
if split[1].length() < 3:
split[1] += "0"
return split[0] + options.thousand_separator + split[1].substr(0,3)
else:
if options.big_decimals == 0 or split[1] == "":
return split[0]
else:
return split[0] + options.decimal_separator + split[1].substr(0,min(options.big_decimals, options.dynamic_numbers - split[0].length() if options.dynamic_decimals else options.big_decimals))
func _latinPower(european_system) -> int:
if european_system:
@warning_ignore("integer_division")
return int(exponent / 3) / 2
@warning_ignore("integer_division")
return int(exponent / 3) - 1
func _latinPrefix(european_system) -> String:
var ones := _latinPower(european_system) % 10
var tens := int(_latinPower(european_system) / floor(10)) % 10
@warning_ignore("integer_division")
var hundreds := int(_latinPower(european_system) / 100) % 10
@warning_ignore("integer_division")
var millias := int(_latinPower(european_system) / 1000) % 10
var prefix := ""
if _latinPower(european_system) < 10:
prefix = latin_special[ones] + options.reading_separator + latin_tens[tens] + options.reading_separator + latin_hundreds[hundreds]
else:
prefix = latin_hundreds[hundreds] + options.reading_separator + latin_ones[ones] + options.reading_separator + latin_tens[tens]
for _i in range(millias):
prefix = "millia" + options.reading_separator + prefix
return prefix.lstrip(options.reading_separator).rstrip(options.reading_separator)
func _tillionOrIllion(european_system) -> String:
if exponent < 6:
return ""
var powerKilo := _latinPower(european_system) % 1000
if powerKilo < 5 and powerKilo > 0 and _latinPower(european_system) < 1000:
return ""
if (
powerKilo >= 7 and powerKilo <= 10
or int(powerKilo / floor(10)) % 10 == 1
):
return "i"
return "ti"
func _llionOrLliard(european_system) -> String:
if exponent < 6:
return ""
if int(exponent/floor(3)) % 2 == 1 and european_system:
return "lliard"
return "llion"
func getLongName(european_system = false, prefix="") -> String:
if exponent < 6:
return ""
else:
return prefix + _latinPrefix(european_system) + options.reading_separator + _tillionOrIllion(european_system) + _llionOrLliard(european_system)
## Converts the Big Number into a string (in American Long Name format)
func toAmericanName(no_decimals_on_small_values = false) -> String:
return toLongName(no_decimals_on_small_values, false)
## Converts the Big Number into a string (in European Long Name format)
func toEuropeanName(no_decimals_on_small_values = false) -> String:
return toLongName(no_decimals_on_small_values, true)
## Converts the Big Number into a string (in Latin Long Name format)
func toLongName(no_decimals_on_small_values = false, european_system = false) -> String:
if exponent < 6:
if exponent > 2:
return toPrefix(no_decimals_on_small_values) + options.suffix_separator + options.thousand_name
else:
return toPrefix(no_decimals_on_small_values)
var suffix = _latinPrefix(european_system) + options.reading_separator + _tillionOrIllion(european_system) + _llionOrLliard(european_system)
return toPrefix(no_decimals_on_small_values) + options.suffix_separator + suffix
## Converts the Big Number into a string (in Metric Symbols format)
func toMetricSymbol(no_decimals_on_small_values = false) -> String:
@warning_ignore("integer_division")
var target := int(exponent / 3)
if not suffixes_metric_symbol.has(str(target)):
return toScientific()
else:
return toPrefix(no_decimals_on_small_values) + options.suffix_separator + suffixes_metric_symbol[str(target)]
## Converts the Big Number into a string (in Metric Name format)
func toMetricName(no_decimals_on_small_values = false) -> String:
@warning_ignore("integer_division")
var target := int(exponent / 3)
if not suffixes_metric_name.has(str(target)):
return toScientific()
else:
return toPrefix(no_decimals_on_small_values) + options.suffix_separator + suffixes_metric_name[str(target)]
# HACK: This function is wasteful and requires remaking.
# It adds new entries to the dictionary suffixes_aa instead of generating the suffixes
# like the other functions
## Converts the Big Number into a string (in AA format)
## @deprecated
func toAA(no_decimals_on_small_values = false, use_thousand_symbol = true, force_decimals=false) -> String:
@warning_ignore("integer_division")
var target := int(exponent / 3)
var aa_index := str(target)
var suffix := ""
if not suffixes_aa.has(aa_index):
var offset := target + 22
var base := alphabet_aa.size()
while offset > 0:
offset -= 1
var digit := offset % base
suffix = alphabet_aa[digit] + suffix
offset /= base
suffixes_aa[aa_index] = suffix
else:
suffix = suffixes_aa[aa_index]
if not use_thousand_symbol and target == 1:
suffix = ""
var prefix = toPrefix(no_decimals_on_small_values, use_thousand_symbol, force_decimals)
return prefix + options.suffix_separator + suffix
|