set bit 0 14 февраля, 2017 Опубликовано 14 февраля, 2017 · Жалоба Код округление числа до десятых. float x = 0; x = 401 * 0.0625; //25.0625 x = x * 10; //250.625 x = x + 0.5; //251.125 x = floor(x); //251 x = x / 10; // Ошибка! При делении 251 на 10, вроде должно быть 25.1, а получается 25.0999995. Если float поменять на double, работает. Но, в маем случае очень не удобно использовать double. Код в другой среде, работает и с float. Понято, что происходит потеря точности. Может есть другой способ округлить число до десятых. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
psL 0 14 февраля, 2017 Опубликовано 14 февраля, 2017 (изменено) · Жалоба попробуйте поделить на 10.0 или умножить на 0.1f Изменено 14 февраля, 2017 пользователем Herz Избыточное цитирование Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Сергей Борщ 135 14 февраля, 2017 Опубликовано 14 февраля, 2017 · Жалоба Понято, что происходит потеря точности.или число 25.1 невозможно представить типом float с принятым у кейла размером мантиссы. Проверьте просто x = 25.1; не слушайте psL, он продемострировал незнание основ языка. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
k155la3 27 14 февраля, 2017 Опубликовано 14 февраля, 2017 (изменено) · Жалоба Код округление числа до десятых. . . . . Может есть другой способ округлить число до десятых. Решение через нетоместо, но решение. Используйте sprintf c указанием точности, напр. %12.1f ps ну и исходник (s)printf можно посмотреть. Изменено 14 февраля, 2017 пользователем k155la3 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Ruslan1 17 14 февраля, 2017 Опубликовано 14 февраля, 2017 · Жалоба При делении 251 на 10, вроде должно быть 25.1, а получается 25.0999995. Кому должно? не должно оно никому. Почитайте представление чисел в float'e, поймете- там величина всегда неточная, она просто в заданном точностью диапазоне. Кстати, по этой же причине грубой ошибкой является попытка проверить float на равенство чему-то. У Вас просто проявилась накопленная во время вычислений (всех вычислений, а не только последнего!) ошибка. Собственно Вы сами уже ответили на свой вопрос: Если float поменять на double, работает. ... Понято, что происходит потеря точности. Вас смутило что "Код в другой среде, работает и с float.". Скорее всего, в этой "другой среде" (уж не Матлаб ли?) оно приводится к длинному представлению и в нем считается, вот и все. Эти ошибки представления не такой очевидный факт. Я лет 15 назад пытался это же объяснить девушке (Программистка, только что окончила Московский Энергетический, очень круто было в наших краях), у нее была ошибка: если она кучу коротких данных (импульсы от счетчиков) преобразовывала в киловатт-часы, то месячная сумма этих коротких величин не сходилась с данными, показанными по барабану счетчика (конец минус начало интервала наблюдения). Причем если взять сумму импульсов за месяц и преобразовать в киловатты, то с барабаном совпадало. Она так и не поняла про точность вычислений, у нее же писи и фокспро, они всегда точно считают. Думала что я над ней так прикалываюсь. :) И не бойтесь использовать дабл, ничего страшного в нем нет. Upd: вот первое попавшееся неплохое описание вопроса. Например, интересен пункт "4.2 Неассоциативность арифметических операций", но там много и другого интересного про подводные камни плавающей точки. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
psL 0 14 февраля, 2017 Опубликовано 14 февраля, 2017 · Жалоба или число 25.1 невозможно представить типом float с принятым у кейла размером мантиссы. Проверьте просто x = 25.1; не слушайте Борща с его принятым размером мантисы. Keil использует IEEE-754: http://www.keil.com/support/man/docs/armli...58938949149.htm которого достаточно для представления 25.1, можно проверить, например, здесь: https://www.h-schmidt.net/FloatConverter/ Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
set bit 0 14 февраля, 2017 Опубликовано 14 февраля, 2017 · Жалоба Ерунда, похоже, с Keil. double Round (double x){ return x=6.1; }; Функция возвращает 6.099998474121, как такое может, быть. https://www.h-schmidt.net/FloatConverter/, проверил 6.1 это 6.099999904632568 похоже, так и есть Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
HardEgor 80 14 февраля, 2017 Опубликовано 14 февраля, 2017 · Жалоба x = 401 * 0.0625; //25.0625 x = x * 10; //250.625 x = x + 0.5; //251.125 x = floor(x); //251 x = x / 10; // Ошибка! А откуда числа в комментариях взялись? Это вы вручную посчитали? А теперь попробуйте вывести результат через sprintf с форматом %e Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
set bit 0 14 февраля, 2017 Опубликовано 14 февраля, 2017 · Жалоба А откуда числа в комментариях взялись? Это вы вручную посчитали? А теперь попробуйте вывести результат через sprintf с форматом %e Да, вручную. Уже понял, свою ошибку. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Сергей Борщ 135 14 февраля, 2017 Опубликовано 14 февраля, 2017 · Жалоба Keil использует IEEE-754: http://www.keil.com/support/man/docs/armli...58938949149.htm Вы бы хоть немного ознакомились с тем, на что ссылаетесь (хотя бы по википедии): Возможные конечные значения, которые могут быть представлены в формате, определяются основанием b, количеством цифр в мантиссе (с точностью р) и максимальным значением emax: И лично вам в коллекцию: неявное приведение типов Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
psL 0 14 февраля, 2017 Опубликовано 14 февраля, 2017 · Жалоба Вы бы хоть немного... И лично вам... Спасибо, конечно, но Вы бы лучше мысль свою пояснили про приведение типов. Смысл моего предложения ТС был в том, что при делении на 10 происходит приведение целого к вещественному с потерей точности, а при умножении вещественных точность выше, чем при делении. В чем я не прав? Только своими словами. Не нужно "братву с википедии" подтягивать. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Сергей Борщ 135 14 февраля, 2017 Опубликовано 14 февраля, 2017 · Жалоба В чем я не прав?В том, что то, что вы предложили (10 ->10.0), компилятор делает сам. То есть ваше предложение эквивалентно "постучать по колесу" из известного анекдота. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Lagman 1 14 февраля, 2017 Опубликовано 14 февраля, 2017 · Жалоба вот есть еще калькулятор который показывает и 25.1 и 25.099998 если выбирать с округлением и без округления. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
slavka012 0 14 февраля, 2017 Опубликовано 14 февраля, 2017 · Жалоба или число 25.1 невозможно представить типом float с принятым у кейла размером мантиссы. Проверьте просто x = 25.1; число 25.1 невозмжно точно представить ни в каком варианте float, хоть double, хоть long double. У Вас просто проявилась накопленная во время вычислений (всех вычислений, а не только последнего!) ошибка. при чем тут накопленная ошибка? после выполнения floor уже все абсолютно точно. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
conan 0 14 февраля, 2017 Опубликовано 14 февраля, 2017 (изменено) · Жалоба В двоичном формате с плавающей запятой точно представимы только целые числа, либо числа дробная часть которых есть сумма (отрицательных) степеней двойки. Нужно умножать дробную часть на 2 до тех пор пока она не обнулится: 0,703125 x 2 = 1,40625 | 1 0,40625 x 2 = 0,8125 | 0 0,8125 x 2 = 1,625 | 1 0,625 x 2 = 1,25 | 1 0,25 x 2 =0,5 | 0 0,5 x 2 = 1 | 1 Т. о. 0,703125 = 0,101101(2) 0.1 сколько на 2 не умножай, дробная часть никогда не обнулится. Т. е. в двоичном виде точно не представимо Изменено 14 февраля, 2017 пользователем conan Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться