Glib: g_ascii_dtostr неточна?

Я немного заинтригован тем, как работают некоторые бойкие функции, такие как "g_ascii_dtostr" (и функции GKeyFile, использующие двойники).

Рассмотрим эту строку:

gchar buf[30];
g_message("Double: %f, as String: %s", 0.2, g_ascii_dtostr(buf, 30, 0.2));

Какие выходы

Double: 0.200000, as String: 0.20000000000000001

(Странное преобразование происходит только тогда, когда я устанавливаю достаточно большой размер буфера)

Аналогичные вещи происходят, когда я (например) сохраняю двойное «1.9» в GKeyFile, но в результирующем файле оно сохраняется как «1.8999999999999999». По-видимому, обратное преобразование через «g_ascii_strtod» должно быть без потерь, но меня все еще беспокоит, почему вообще происходит эта странность. Кроме того, это делает мои файлы конфигурации "ключ-значение" довольно уродливыми.

Я думаю, что однажды где-то читал, что используется промежуточный тип «длинный двойной», но это все равно не объясняет, почему преобразованное значение «грязное», потому что, например. я думаю, что преобразование из int в double for не имеет подобных эффектов.


person Ancurio    schedule 31.12.2011    source источник
comment
docs.oracle.com/cd/E19957-01/806- 3568/ncg_goldberg.html   -  person Mysticial    schedule 31.12.2011
comment
Указатель на наиболее частый ответ, связанный с плавающей запятой, в stackoverflow (или где-либо еще?): stackoverflow.com/a/6033242/12711   -  person Michael Burr    schedule 31.12.2011
comment
@Mysticial Спасибо, я прочитаю эту статью позже, но сейчас, в основном, когда я сохраняю значение 1,9, оно никогда не могло быть сохранено точно в первую очередь, потому что в двоичном формате оно имеет бесконечные цифры. Это правильно?   -  person Ancurio    schedule 31.12.2011
comment
Если вы измените %f на %.18f, вы также увидите аналогичный вывод литерала 0.2.   -  person caf    schedule 31.12.2011
comment
player.vimeo.com/video/7516539#t=7m26s короткий и веселье.   -  person Yasushi Shoji    schedule 19.08.2012


Ответы (1)


Из документации:

«Эта функция генерирует достаточную точность, поэтому преобразование строки обратно с помощью g_ascii_strtod() дает тот же номер машины (на машинах с 64-битными двойниками, совместимыми с IEEE)».

Как заметил caf в своем комментарии, спецификатор %f усекается после шести десятичных цифр, поэтому g_ascii_strtod() дает более точное значение. Вы можете использовать g_ascii_formatd(), если хотите это усечение.

person Michael C.    schedule 08.11.2013