Ответ 1
Это дефект, который присутствует во всех версиях Delphi, которые используют версию StrToFloat
для StrToFloat
. Это сопоставляется с InternalTextToExtended
который читает экспоненту следующим образом:
function ReadExponent: SmallInt;
var
LSign: SmallInt;
begin
LSign := ReadSign();
Result := 0;
while LCurrChar.IsDigit do
begin
Result := Result * 10;
Result := Result + Ord(LCurrChar) - Ord('0');
NextChar();
end;
if Result > CMaxExponent then
Result := CMaxExponent;
Result := Result * LSign;
end;
Проблема заключается в
if Result > CMaxExponent then
Этот тест предназначен для внутри цикла, а в версии asm x86 этого кода он есть. Как указано выше, с максимальным показателем экспоненты вне цикла, 16-разрядное значение целочисленного значения со 99999999
слишком велико для вашего показателя 99999999
. Когда показатель экспоненты считывается, значение в Result
переполняется и становится отрицательным. Итак, для вашего примера получается, что используется показатель -7937
а не 99999999
. Естественно, это приводит к нулю.
Это явная ошибка, и я представил отчет об ошибке: RSP-20333.
Что касается того, как обойти эту проблему, я не знаю о другой функции в Delphi RTL, которая выполняет эту задачу. Поэтому я думаю, вам нужно будет сделать одно из следующего:
-
StrToFloat
свой собственныйStrToFloat
. - Предварительно обработайте строку и обработайте экспоненты диапазона до того, как они прочитают
StrToFloat
. - Используйте одну из функций из библиотеки времени выполнения C, которая выполняет одну и ту же задачу.
Наконец, я благодарен вам за то, что вы задали этот вопрос, потому что я вижу, что на мою собственную программу влияет этот дефект, и теперь я могу это исправить!
Обновить:
Вам также может быть интересно посмотреть на связанную ошибку, которую я обнаружил при расследовании: RSP-20334. Это может удивить вас, что StrToFloat('߀')
при использовании версии StrToFloat
возвращает 1936.0
. Фокус в том, что символ, который передается StrToFloat
является нелатинской цифрой, в данном случае U + 07C0.