(и просто присваивая непосредственно двойному), чтобы убедиться, что это происходит в

я проблема в системах на основе UNIX. Sprintf не округляет значение должным образом.

Например

double tmp = 88888888888885.875
char out[512];

Это 88,888,888,888,885,875, чтобы быть проще для глаз. Я привожу такой конкретный и большой пример, потому что кажется, что он отлично работает на меньших числах.

Я пытаюсь использовать это следующим образом

sprintf(out, "%021.2f", tmp);
printf("out = %s\n", tmp);

На окнах это приводит к:

out = 000088888888888885.88

Например, в AIX, но также и в Linux:

out = 000088888888888885.87

Почему это происходит? Любые идеи и как заставить его вести себя одинаково на Win / Unix

Спасибо

 rajah910 янв. 2011 г., 18:42
Пожалуйста, посмотрите наstackoverflow.com/questions/994764/rounding-doubles-5-sprintf, Разница между вашей долей (0,875) и его долей (0,555) в том, что ваша может быть выражена точно в двоичном виде; это 7/8.
 aschepler10 янв. 2011 г., 18:49
На большинстве компьютеров используется 64-битная IEEEdouble твои двоеout обе строки равны исходному (точному) значениюtmp.
 Charles Salvia10 янв. 2011 г., 18:41
На Linux (Debian 5) AMD64 я получаю000088888888888885.88
 Nim10 янв. 2011 г., 18:29
эм,ideone.com/UVtft отчеты.88мой местный SuseLinux сообщает то же самое ...
 chrisaycock10 янв. 2011 г., 18:33
Какие процессоры вы используете для каждой ОС?

Ответы на вопрос(4)

и вашим компилятором?

Не все процессоры используют один и тот же способ представления значений с плавающей точкой, и даже компиляторы могут выбирать разные методы представления с плавающей точкой (я думаю, что компилятор Microsoft C ++ даже имеет опции для выбора представления).

Страницаhttp://www.quadibloc.com/comp/cp0201.htm дает обзор некоторых представлений с плавающей точкой (хотя они, кажется, довольно старые архитектуры, показанные там).

http://msdn.microsoft.com/en-us/library/0b34tf65.aspx описывает, как Microsoft Visual C ++ хранит значения с плавающей точкой. Я не мог сразу найти, какое представление используется в AIX или Linux.

Кроме того, у каждого компилятора есть опции, которые позволяют вам указать, как вы хотите работать с операциями с плавающей запятой. Вы хотите, чтобы они были максимально точными (но, возможно, несколько медленнее)? Или вы хотите, чтобы операции с плавающей точкой были максимально быстрыми (но, возможно, менее корректными)?

 Puppy10 янв. 2011 г., 18:53
MSVC не может выбрать представление, его параметры касаются оптимизаций, которые он выполняет для арифметики с плавающей точкой и методов.
 mizo10 янв. 2011 г., 18:53
Вот интересный связанный вопрос:stackoverflow.com/questions/1961442/...
Решение Вопроса

сообщение об ошибке для glibc с проблемой очень похожей на вашу. Основной вывод (в комментарии 46) здесь состоит в том, что double - это не 15-десятичное число, и вы не должны ожидать, что оно будет работать так.

В качестве обходного пути вы можете добавить что-то маленькое к своим числам, чтобы сделать их лучше. Но это решение не является общим, потому что оно зависит от диапазонов номеров, с которыми вы имеете дело.

Другим обходным решением может быть умножение, чтобы подготовить их к округлению, затем округление (например,2597.625*100 = 259762.5 -> 259763 = 2597.63*100)

Однако я думаю, что должны быть более разумные обходные пути.

 grobartn12 янв. 2011 г., 18:43
Я не использовал ваш обходной путь, но верхняя часть - то, что мне было нужно, спасибо

соответствующей стандарту IEEE 754, должно быть напечатано88888888888885.88 в режиме округления по умолчанию. Это не имеет ничего общего с точностью с плавающей точкой, так как значение точно представимо; это просто вопросprintfокругление до 2 знаков после запятой. Понятия не имею, почему вы видите88888888888885.87 на некоторых системах.

 Cascabel10 янв. 2011 г., 19:36
ФП может попытаться опуститьsprintf (и просто присваивая непосредственно двойному), чтобы убедиться, что это происходит вprintf.

double который имеет ограничения точности, то есть ваш88888888888885.875 вероятно, округляется до чего-то еще внутри.

Посмотреть больше информациив аналогичном вопросе, вблоги или ввикипедия.

 Grammin10 янв. 2011 г., 18:37
Да, почему двойное число по-разному округляется в разных ОС? Конечно, у него есть ограничения точности, поэтому он получает разные ответы.
 Miguel Ventura10 янв. 2011 г., 18:40
Это может варьироваться от архитектуры блока до некоторой полировки, выполняемой libc printf. Как видно из комментариев к вопросу, даже в одной и той же ОС (Linux) он ведет себя по-разному, потому что по сути нет гарантии, что он должен вести себя одинаково.

Ваш ответ на вопрос