set bit 0 Posted February 14, 2017 · Report post Код округление числа до десятых. 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. Понято, что происходит потеря точности. Может есть другой способ округлить число до десятых. Quote Ответить с цитированием Share this post Link to post Share on other sites
psL 0 Posted February 14, 2017 (edited) · Report post попробуйте поделить на 10.0 или умножить на 0.1f Edited February 14, 2017 by Herz Избыточное цитирование Quote Ответить с цитированием Share this post Link to post Share on other sites
Сергей Борщ 0 Posted February 14, 2017 · Report post Понято, что происходит потеря точности.или число 25.1 невозможно представить типом float с принятым у кейла размером мантиссы. Проверьте просто x = 25.1; не слушайте psL, он продемострировал незнание основ языка. Quote Ответить с цитированием Share this post Link to post Share on other sites
k155la3 0 Posted February 14, 2017 (edited) · Report post Код округление числа до десятых. . . . . Может есть другой способ округлить число до десятых. Решение через нетоместо, но решение. Используйте sprintf c указанием точности, напр. %12.1f ps ну и исходник (s)printf можно посмотреть. Edited February 14, 2017 by k155la3 Quote Ответить с цитированием Share this post Link to post Share on other sites
Ruslan1 0 Posted February 14, 2017 · Report post При делении 251 на 10, вроде должно быть 25.1, а получается 25.0999995. Кому должно? не должно оно никому. Почитайте представление чисел в float'e, поймете- там величина всегда неточная, она просто в заданном точностью диапазоне. Кстати, по этой же причине грубой ошибкой является попытка проверить float на равенство чему-то. У Вас просто проявилась накопленная во время вычислений (всех вычислений, а не только последнего!) ошибка. Собственно Вы сами уже ответили на свой вопрос: Если float поменять на double, работает. ... Понято, что происходит потеря точности. Вас смутило что "Код в другой среде, работает и с float.". Скорее всего, в этой "другой среде" (уж не Матлаб ли?) оно приводится к длинному представлению и в нем считается, вот и все. Эти ошибки представления не такой очевидный факт. Я лет 15 назад пытался это же объяснить девушке (Программистка, только что окончила Московский Энергетический, очень круто было в наших краях), у нее была ошибка: если она кучу коротких данных (импульсы от счетчиков) преобразовывала в киловатт-часы, то месячная сумма этих коротких величин не сходилась с данными, показанными по барабану счетчика (конец минус начало интервала наблюдения). Причем если взять сумму импульсов за месяц и преобразовать в киловатты, то с барабаном совпадало. Она так и не поняла про точность вычислений, у нее же писи и фокспро, они всегда точно считают. Думала что я над ней так прикалываюсь. :) И не бойтесь использовать дабл, ничего страшного в нем нет. Upd: вот первое попавшееся неплохое описание вопроса. Например, интересен пункт "4.2 Неассоциативность арифметических операций", но там много и другого интересного про подводные камни плавающей точки. Quote Ответить с цитированием Share this post Link to post Share on other sites
psL 0 Posted February 14, 2017 · Report post или число 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/ Quote Ответить с цитированием Share this post Link to post Share on other sites
set bit 0 Posted February 14, 2017 · Report post Ерунда, похоже, с Keil. double Round (double x){ return x=6.1; }; Функция возвращает 6.099998474121, как такое может, быть. https://www.h-schmidt.net/FloatConverter/, проверил 6.1 это 6.099999904632568 похоже, так и есть Quote Ответить с цитированием Share this post Link to post Share on other sites
HardEgor 0 Posted February 14, 2017 · Report post 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 Quote Ответить с цитированием Share this post Link to post Share on other sites
set bit 0 Posted February 14, 2017 · Report post А откуда числа в комментариях взялись? Это вы вручную посчитали? А теперь попробуйте вывести результат через sprintf с форматом %e Да, вручную. Уже понял, свою ошибку. Quote Ответить с цитированием Share this post Link to post Share on other sites
Сергей Борщ 0 Posted February 14, 2017 · Report post Keil использует IEEE-754: http://www.keil.com/support/man/docs/armli...58938949149.htm Вы бы хоть немного ознакомились с тем, на что ссылаетесь (хотя бы по википедии): Возможные конечные значения, которые могут быть представлены в формате, определяются основанием b, количеством цифр в мантиссе (с точностью р) и максимальным значением emax: И лично вам в коллекцию: неявное приведение типов Quote Ответить с цитированием Share this post Link to post Share on other sites
psL 0 Posted February 14, 2017 · Report post Вы бы хоть немного... И лично вам... Спасибо, конечно, но Вы бы лучше мысль свою пояснили про приведение типов. Смысл моего предложения ТС был в том, что при делении на 10 происходит приведение целого к вещественному с потерей точности, а при умножении вещественных точность выше, чем при делении. В чем я не прав? Только своими словами. Не нужно "братву с википедии" подтягивать. Quote Ответить с цитированием Share this post Link to post Share on other sites
Сергей Борщ 0 Posted February 14, 2017 · Report post В чем я не прав?В том, что то, что вы предложили (10 ->10.0), компилятор делает сам. То есть ваше предложение эквивалентно "постучать по колесу" из известного анекдота. Quote Ответить с цитированием Share this post Link to post Share on other sites
Lagman 0 Posted February 14, 2017 · Report post вот есть еще калькулятор который показывает и 25.1 и 25.099998 если выбирать с округлением и без округления. Quote Ответить с цитированием Share this post Link to post Share on other sites
slavka012 0 Posted February 14, 2017 · Report post или число 25.1 невозможно представить типом float с принятым у кейла размером мантиссы. Проверьте просто x = 25.1; число 25.1 невозмжно точно представить ни в каком варианте float, хоть double, хоть long double. У Вас просто проявилась накопленная во время вычислений (всех вычислений, а не только последнего!) ошибка. при чем тут накопленная ошибка? после выполнения floor уже все абсолютно точно. Quote Ответить с цитированием Share this post Link to post Share on other sites
conan 0 Posted February 14, 2017 (edited) · Report post В двоичном формате с плавающей запятой точно представимы только целые числа, либо числа дробная часть которых есть сумма (отрицательных) степеней двойки. Нужно умножать дробную часть на 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 не умножай, дробная часть никогда не обнулится. Т. е. в двоичном виде точно не представимо Edited February 14, 2017 by conan Quote Ответить с цитированием Share this post Link to post Share on other sites