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:
+6
-25
@@ -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):
|
||||
|
||||
Reference in New Issue
Block a user