diff --git a/GFramework.Game.Tests/Config/YamlConfigLoaderTests.cs b/GFramework.Game.Tests/Config/YamlConfigLoaderTests.cs index 29d57119..a8f45394 100644 --- a/GFramework.Game.Tests/Config/YamlConfigLoaderTests.cs +++ b/GFramework.Game.Tests/Config/YamlConfigLoaderTests.cs @@ -558,6 +558,50 @@ public class YamlConfigLoaderTests }); } + /// + /// 验证大数值配合十进制步进时,会沿用 JS 工具侧的 multipleOf 容差策略。 + /// + [Test] + public async Task LoadAsync_Should_Accept_Large_Decimal_Number_When_MultipleOf_Matches_Js_Tolerance() + { + CreateConfigFile( + "monster/slime.yaml", + """ + id: 1 + dropRate: 10000000.2 + """); + CreateSchemaFile( + "schemas/monster.schema.json", + """ + { + "type": "object", + "required": ["id", "dropRate"], + "properties": { + "id": { "type": "integer" }, + "dropRate": { + "type": "number", + "multipleOf": 0.1 + } + } + } + """); + + var loader = new YamlConfigLoader(_rootPath) + .RegisterTable("monster", "monster", "schemas/monster.schema.json", + static config => config.Id); + var registry = new ConfigRegistry(); + + await loader.LoadAsync(registry); + + var table = registry.GetTable("monster"); + + Assert.Multiple(() => + { + Assert.That(table.Count, Is.EqualTo(1)); + Assert.That(table.Get(1).DropRate, Is.EqualTo(10000000.2d)); + }); + } + /// /// 验证科学计数法数值会按 number 类型被运行时接受。 /// diff --git a/GFramework.Game/Config/YamlConfigSchemaValidator.cs b/GFramework.Game/Config/YamlConfigSchemaValidator.cs index f7dc74c4..efeda8fa 100644 --- a/GFramework.Game/Config/YamlConfigSchemaValidator.cs +++ b/GFramework.Game/Config/YamlConfigSchemaValidator.cs @@ -1745,9 +1745,9 @@ internal static class YamlConfigSchemaValidator /// /// 判断数值是否满足 multipleOf。 - /// 双精度浮点比较会保留一个与步进量级相关的微小容差, - /// 以避免运行时与 JS 工具侧在 0.1 / 0.01 这类十进制步进上出现伪失败, - /// 同时避免值越大就无限放宽合法余数范围。 + /// 双精度浮点比较会在商空间保留一个与商量级相关的微小容差, + /// 以对齐 JS 工具侧对 0.1 / 0.01 这类十进制步进的判定方式, + /// 避免出现“编辑器通过、运行时拒绝”的跨环境漂移。 /// /// 当前值。 /// 步进约束。 @@ -1756,8 +1756,8 @@ internal static class YamlConfigSchemaValidator { var quotient = value / divisor; var nearestInteger = Math.Round(quotient); - var tolerance = 1e-9 * Math.Max(1d, Math.Abs(divisor)); - return Math.Abs(value - (nearestInteger * divisor)) <= tolerance; + var tolerance = 1e-9 * Math.Max(1d, Math.Abs(quotient)); + return Math.Abs(quotient - nearestInteger) <= tolerance; } ///