Add exact arithmetic implementation and tests

- Introduced exact arithmetic with support for large integers and fractions in `exact.gd`, `big_integer.gd`, and `exact_value.gd`.
- Implemented a comprehensive test suite in `test_exact_math.gd` to validate arithmetic operations against expected results.
- Added a README in `math` directory to document the exact arithmetic system and its usage.
- Ensured that all arithmetic operations maintain precision without floating-point errors, using a custom representation for large numbers.
- Included methods for encoding and decoding exact values for serialization.
This commit is contained in:
Kirill
2026-09-30 08:08:27 +03:00
parent f2111a376a
commit fb8a3f5658
58 changed files with 5139 additions and 2162 deletions
+6 -25
View File
@@ -1,4 +1,5 @@
extends Node
const E = preload("res://world/owniverse/math/exact.gd")
const SPEED_LIMIT: int = 6
@@ -57,37 +58,15 @@ func get_description(item_id: String, items: Array = []) -> String:
return render_template(row, variables)
func format_number(value: float, digits: int = 0) -> String:
if value == 0: return ""
# Keep ordinary quantities readable, grouping thousands with spaces.
# Scientific notation is reserved for values whose fixed form would be
# unwieldy in the UI.
if absf(value) < 1_000_000_000.0:
var fixed: String = "%.*f" % [digits, value]
var parts: PackedStringArray = fixed.split(".", true)
var integer: String = parts[0]
var sign_prefix: String = ""
if integer.begins_with("-") or integer.begins_with("+"):
sign_prefix = integer.left(1)
integer = integer.substr(1)
var grouped: String = ""
while integer.length() > 3:
grouped = " " + integer.right(3) + grouped
integer = integer.left(integer.length() - 3)
grouped = sign_prefix + integer + grouped
return grouped + ("." + parts[1] if parts.size() > 1 else "")
var exp_value = int(floor(log(abs(value)) / log(10.0)))
var mantissa = value / pow(10.0, exp_value)
return "%.*f" % [digits, mantissa] + "E%+d" % exp_value
func format_number(value, digits: int = 0) -> String:
return E.grouped(value, digits)
func _ready() -> void:
CivilizationRules.clear()
for row: Dictionary in _read_from_csv("res://data/civilization_rules.txt").values():
if not CivilizationRules.has(row.stage):
CivilizationRules[row.stage] = {"home": row.home, "span": float(row.span), "stars": float(row.stars), "ethics": {},
CivilizationRules[row.stage] = {"home": row.home, "span": E.of(row.span), "stars": E.of(row.stars), "ethics": {},
"colonizes": row.colonizes == "1", "fights": row.fights == "1", "diplomacy": row.diplomacy == "1", "worships": row.worships == "1"}
CivilizationRules[row.stage].ethics[row.ethic] = row
var stages: Array = CivilizationRules.keys()
@@ -107,6 +86,8 @@ func _ready() -> void:
Templates["en"] = _read_from_csv("res://data/templates.en.txt")
Templates["ru"] = _read_from_csv("res://data/templates.ru.txt")
#Templates = OwniverseTemplates.get_data()
func _read_from_csv(file_path: String) -> Dictionary:
if not FileAccess.file_exists(file_path):