Delphi 的 Round() 似乎是不确定的
Delphi's Round() appears to be non-deterministic
我遇到了一个奇怪的情况,同一台机器上的同一程序对相同的浮点值执行 Round()
并不总是给出相同的结果。起初我认为它一定是因为有点翻转或其他原因而出现故障,但它一直在回来。现在它也开始发生在一台完全不同的机器上。糟糕的结果很少出现,大约每周一次。当他们这样做时,他们似乎一直在发生,直到程序重新启动。然而,这可能是巧合。到目前为止,我无法随意复制它。顺便说一下,这一切都发生在主线程上。
我考虑添加的一项检查是 Round
是否一直指向相同的内存地址。还有其他想法吗?
2020-12-28 08:30:19.411 DBGrid1.Fields[17].AsString: 0,239999994635582
2020-12-28 08:30:19.411 FloatToStr(DBGrid1.Fields[17].AsFloat): 0,239999994635582
2020-12-28 08:30:19.411 FloatToStr(1000 * DBGrid1.Fields[17].AsFloat): 239,999994635582
2020-12-28 08:30:19.411 IntToStr(Round(1000 * DBGrid1.Fields[17].AsFloat)): 239
2020-12-28 08:30:19.411 FloatToStr(DBGrid1.Fields[17].AsSingle): 0,239999994635582
2020-12-28 08:30:19.411 FloatToStr(1000 * DBGrid1.Fields[17].AsSingle): 239,999994635582
2020-12-28 08:30:19.411 IntToStr(Round(1000 * DBGrid1.Fields[17].AsSingle)): 239
2020-12-28 08:30:19.411 FloatToStr(DBGrid1.Fields[17].AsExtended): 0,239999994635582
2020-12-28 08:30:19.412 FloatToStr(1000 * DBGrid1.Fields[17].AsExtended): 239,999994635582
2020-12-28 08:30:19.412 IntToStr(Round(1000 * DBGrid1.Fields[17].AsExtended)): 239
2020-12-28 08:30:19.412 CurrToStr(DBGrid1.Fields[17].AsCurrency): 0,2399
2020-12-28 08:30:19.412 CurrToStr(1000 * DBGrid1.Fields[17].AsCurrency): 239,9
2020-12-28 08:30:19.412 IntToStr(Round(1000 * DBGrid1.Fields[17].AsCurrency)): 239
2020-12-28 08:30:19.412 FloatToStr(Query1.FieldByName('FIELD').AsFloat): 0,239999994635582
2020-12-28 08:30:19.412 FloatToStr(1000 * Query1.FieldByName('FIELD').AsFloat): 239,999994635582
2020-12-28 08:30:19.412 IntToStr(Round(1000 * Query1.FieldByName('FIELD').AsFloat)): 239
2020-12-28 08:30:19.412 FloatToStr(Query1.FieldByName('FIELD').AsSingle): 0,239999994635582
2020-12-28 08:30:19.412 FloatToStr(1000 * Query1.FieldByName('FIELD').AsSingle): 239,999994635582
2020-12-28 08:30:19.413 IntToStr(Round(1000 * Query1.FieldByName('FIELD').AsSingle)): 239
2020-12-28 08:30:19.413 FloatToStr(Query1.FieldByName('FIELD').AsExtended): 0,239999994635582
2020-12-28 08:30:19.413 FloatToStr(1000 * Query1.FieldByName('FIELD').AsExtended): 239,999994635582
2020-12-28 08:30:19.413 IntToStr(Round(1000 * Query1.FieldByName('FIELD').AsExtended)): 239
2020-12-28 08:30:19.413 CurrToStr(Query1.FieldByName('FIELD').AsCurrency): 0,2399
2020-12-28 08:30:19.413 CurrToStr(1000 * Query1.FieldByName('FIELD').AsCurrency): 239,9
2020-12-28 08:30:19.413 IntToStr(Round(1000 * Query1.FieldByName('FIELD').AsCurrency)): 239
2020-12-28 08:30:19.413 CurrToStr(Query1.FieldByName('FIELD').AsCurrency): 0,2399
2020-12-28 08:30:19.413 CurrToStr(1000 * Query1.FieldByName('FIELD').AsCurrency): 239,9
2020-12-28 08:30:19.413 IntToStr(Round(1000 * Query1.FieldByName('FIELD').AsCurrency)): 239
2020-12-28 08:30:19.414 BinToHex(DBGrid1.Fields[17].AsFloat): 00000000008FC2F5FC3F
2020-12-28 08:40:46.461 DBGrid1.Fields[17].AsString: 0,239999994635582
2020-12-28 08:40:46.462 FloatToStr(DBGrid1.Fields[17].AsFloat): 0,239999994635582
2020-12-28 08:40:46.463 FloatToStr(1000 * DBGrid1.Fields[17].AsFloat): 239,999994635582
2020-12-28 08:40:46.463 IntToStr(Round(1000 * DBGrid1.Fields[17].AsFloat)): 240
2020-12-28 08:40:46.463 FloatToStr(DBGrid1.Fields[17].AsSingle): 0,239999994635582
2020-12-28 08:40:46.463 FloatToStr(1000 * DBGrid1.Fields[17].AsSingle): 239,999994635582
2020-12-28 08:40:46.463 IntToStr(Round(1000 * DBGrid1.Fields[17].AsSingle)): 240
2020-12-28 08:40:46.463 FloatToStr(DBGrid1.Fields[17].AsExtended): 0,239999994635582
2020-12-28 08:40:46.463 FloatToStr(1000 * DBGrid1.Fields[17].AsExtended): 239,999994635582
2020-12-28 08:40:46.463 IntToStr(Round(1000 * DBGrid1.Fields[17].AsExtended)): 240
2020-12-28 08:40:46.463 CurrToStr(DBGrid1.Fields[17].AsCurrency): 0,24
2020-12-28 08:40:46.463 CurrToStr(1000 * DBGrid1.Fields[17].AsCurrency): 240
2020-12-28 08:40:46.463 IntToStr(Round(1000 * DBGrid1.Fields[17].AsCurrency)): 240
2020-12-28 08:40:46.463 FloatToStr(Query1.FieldByName('FIELD').AsFloat): 0,239999994635582
2020-12-28 08:40:46.463 FloatToStr(1000 * Query1.FieldByName('FIELD').AsFloat): 239,999994635582
2020-12-28 08:40:46.463 IntToStr(Round(1000 * Query1.FieldByName('FIELD').AsFloat)): 240
2020-12-28 08:40:46.463 FloatToStr(Query1.FieldByName('FIELD').AsSingle): 0,239999994635582
2020-12-28 08:40:46.464 FloatToStr(1000 * Query1.FieldByName('FIELD').AsSingle): 239,999994635582
2020-12-28 08:40:46.464 IntToStr(Round(1000 * Query1.FieldByName('FIELD').AsSingle)): 240
2020-12-28 08:40:46.464 FloatToStr(Query1.FieldByName('FIELD').AsExtended): 0,239999994635582
2020-12-28 08:40:46.464 FloatToStr(1000 * Query1.FieldByName('FIELD').AsExtended): 239,999994635582
2020-12-28 08:40:46.464 IntToStr(Round(1000 * Query1.FieldByName('FIELD').AsExtended)): 240
2020-12-28 08:40:46.464 CurrToStr(Query1.FieldByName('FIELD').AsCurrency): 0,24
2020-12-28 08:40:46.464 CurrToStr(1000 * Query1.FieldByName('FIELD').AsCurrency): 240
2020-12-28 08:40:46.464 IntToStr(Round(1000 * Query1.FieldByName('FIELD').AsCurrency)): 240
2020-12-28 08:40:46.464 CurrToStr(Query1.FieldByName('FIELD').AsCurrency): 0,24
2020-12-28 08:40:46.464 CurrToStr(1000 * Query1.FieldByName('FIELD').AsCurrency): 240
2020-12-28 08:40:46.465 IntToStr(Round(1000 * Query1.FieldByName('FIELD').AsCurrency)): 240
2020-12-28 08:40:46.465 BinToHex(DBGrid1.Fields[17].AsFloat): 00000000008FC2F5FC3F
Round
是确定性的。但是,它的行为取决于流行的浮点舍入模式及其参数。您程序中的其他内容正在更改舍入模式。
我遇到了一个奇怪的情况,同一台机器上的同一程序对相同的浮点值执行 Round()
并不总是给出相同的结果。起初我认为它一定是因为有点翻转或其他原因而出现故障,但它一直在回来。现在它也开始发生在一台完全不同的机器上。糟糕的结果很少出现,大约每周一次。当他们这样做时,他们似乎一直在发生,直到程序重新启动。然而,这可能是巧合。到目前为止,我无法随意复制它。顺便说一下,这一切都发生在主线程上。
我考虑添加的一项检查是 Round
是否一直指向相同的内存地址。还有其他想法吗?
2020-12-28 08:30:19.411 DBGrid1.Fields[17].AsString: 0,239999994635582
2020-12-28 08:30:19.411 FloatToStr(DBGrid1.Fields[17].AsFloat): 0,239999994635582
2020-12-28 08:30:19.411 FloatToStr(1000 * DBGrid1.Fields[17].AsFloat): 239,999994635582
2020-12-28 08:30:19.411 IntToStr(Round(1000 * DBGrid1.Fields[17].AsFloat)): 239
2020-12-28 08:30:19.411 FloatToStr(DBGrid1.Fields[17].AsSingle): 0,239999994635582
2020-12-28 08:30:19.411 FloatToStr(1000 * DBGrid1.Fields[17].AsSingle): 239,999994635582
2020-12-28 08:30:19.411 IntToStr(Round(1000 * DBGrid1.Fields[17].AsSingle)): 239
2020-12-28 08:30:19.411 FloatToStr(DBGrid1.Fields[17].AsExtended): 0,239999994635582
2020-12-28 08:30:19.412 FloatToStr(1000 * DBGrid1.Fields[17].AsExtended): 239,999994635582
2020-12-28 08:30:19.412 IntToStr(Round(1000 * DBGrid1.Fields[17].AsExtended)): 239
2020-12-28 08:30:19.412 CurrToStr(DBGrid1.Fields[17].AsCurrency): 0,2399
2020-12-28 08:30:19.412 CurrToStr(1000 * DBGrid1.Fields[17].AsCurrency): 239,9
2020-12-28 08:30:19.412 IntToStr(Round(1000 * DBGrid1.Fields[17].AsCurrency)): 239
2020-12-28 08:30:19.412 FloatToStr(Query1.FieldByName('FIELD').AsFloat): 0,239999994635582
2020-12-28 08:30:19.412 FloatToStr(1000 * Query1.FieldByName('FIELD').AsFloat): 239,999994635582
2020-12-28 08:30:19.412 IntToStr(Round(1000 * Query1.FieldByName('FIELD').AsFloat)): 239
2020-12-28 08:30:19.412 FloatToStr(Query1.FieldByName('FIELD').AsSingle): 0,239999994635582
2020-12-28 08:30:19.412 FloatToStr(1000 * Query1.FieldByName('FIELD').AsSingle): 239,999994635582
2020-12-28 08:30:19.413 IntToStr(Round(1000 * Query1.FieldByName('FIELD').AsSingle)): 239
2020-12-28 08:30:19.413 FloatToStr(Query1.FieldByName('FIELD').AsExtended): 0,239999994635582
2020-12-28 08:30:19.413 FloatToStr(1000 * Query1.FieldByName('FIELD').AsExtended): 239,999994635582
2020-12-28 08:30:19.413 IntToStr(Round(1000 * Query1.FieldByName('FIELD').AsExtended)): 239
2020-12-28 08:30:19.413 CurrToStr(Query1.FieldByName('FIELD').AsCurrency): 0,2399
2020-12-28 08:30:19.413 CurrToStr(1000 * Query1.FieldByName('FIELD').AsCurrency): 239,9
2020-12-28 08:30:19.413 IntToStr(Round(1000 * Query1.FieldByName('FIELD').AsCurrency)): 239
2020-12-28 08:30:19.413 CurrToStr(Query1.FieldByName('FIELD').AsCurrency): 0,2399
2020-12-28 08:30:19.413 CurrToStr(1000 * Query1.FieldByName('FIELD').AsCurrency): 239,9
2020-12-28 08:30:19.413 IntToStr(Round(1000 * Query1.FieldByName('FIELD').AsCurrency)): 239
2020-12-28 08:30:19.414 BinToHex(DBGrid1.Fields[17].AsFloat): 00000000008FC2F5FC3F
2020-12-28 08:40:46.461 DBGrid1.Fields[17].AsString: 0,239999994635582
2020-12-28 08:40:46.462 FloatToStr(DBGrid1.Fields[17].AsFloat): 0,239999994635582
2020-12-28 08:40:46.463 FloatToStr(1000 * DBGrid1.Fields[17].AsFloat): 239,999994635582
2020-12-28 08:40:46.463 IntToStr(Round(1000 * DBGrid1.Fields[17].AsFloat)): 240
2020-12-28 08:40:46.463 FloatToStr(DBGrid1.Fields[17].AsSingle): 0,239999994635582
2020-12-28 08:40:46.463 FloatToStr(1000 * DBGrid1.Fields[17].AsSingle): 239,999994635582
2020-12-28 08:40:46.463 IntToStr(Round(1000 * DBGrid1.Fields[17].AsSingle)): 240
2020-12-28 08:40:46.463 FloatToStr(DBGrid1.Fields[17].AsExtended): 0,239999994635582
2020-12-28 08:40:46.463 FloatToStr(1000 * DBGrid1.Fields[17].AsExtended): 239,999994635582
2020-12-28 08:40:46.463 IntToStr(Round(1000 * DBGrid1.Fields[17].AsExtended)): 240
2020-12-28 08:40:46.463 CurrToStr(DBGrid1.Fields[17].AsCurrency): 0,24
2020-12-28 08:40:46.463 CurrToStr(1000 * DBGrid1.Fields[17].AsCurrency): 240
2020-12-28 08:40:46.463 IntToStr(Round(1000 * DBGrid1.Fields[17].AsCurrency)): 240
2020-12-28 08:40:46.463 FloatToStr(Query1.FieldByName('FIELD').AsFloat): 0,239999994635582
2020-12-28 08:40:46.463 FloatToStr(1000 * Query1.FieldByName('FIELD').AsFloat): 239,999994635582
2020-12-28 08:40:46.463 IntToStr(Round(1000 * Query1.FieldByName('FIELD').AsFloat)): 240
2020-12-28 08:40:46.463 FloatToStr(Query1.FieldByName('FIELD').AsSingle): 0,239999994635582
2020-12-28 08:40:46.464 FloatToStr(1000 * Query1.FieldByName('FIELD').AsSingle): 239,999994635582
2020-12-28 08:40:46.464 IntToStr(Round(1000 * Query1.FieldByName('FIELD').AsSingle)): 240
2020-12-28 08:40:46.464 FloatToStr(Query1.FieldByName('FIELD').AsExtended): 0,239999994635582
2020-12-28 08:40:46.464 FloatToStr(1000 * Query1.FieldByName('FIELD').AsExtended): 239,999994635582
2020-12-28 08:40:46.464 IntToStr(Round(1000 * Query1.FieldByName('FIELD').AsExtended)): 240
2020-12-28 08:40:46.464 CurrToStr(Query1.FieldByName('FIELD').AsCurrency): 0,24
2020-12-28 08:40:46.464 CurrToStr(1000 * Query1.FieldByName('FIELD').AsCurrency): 240
2020-12-28 08:40:46.464 IntToStr(Round(1000 * Query1.FieldByName('FIELD').AsCurrency)): 240
2020-12-28 08:40:46.464 CurrToStr(Query1.FieldByName('FIELD').AsCurrency): 0,24
2020-12-28 08:40:46.464 CurrToStr(1000 * Query1.FieldByName('FIELD').AsCurrency): 240
2020-12-28 08:40:46.465 IntToStr(Round(1000 * Query1.FieldByName('FIELD').AsCurrency)): 240
2020-12-28 08:40:46.465 BinToHex(DBGrid1.Fields[17].AsFloat): 00000000008FC2F5FC3F
Round
是确定性的。但是,它的行为取决于流行的浮点舍入模式及其参数。您程序中的其他内容正在更改舍入模式。