Округление с точностью до заданного числа
- Войдите на сайт для отправки комментариев
Вс, 30/10/2016 - 23:00
Господа. Понадобилось округлять значение переменной (float) c точностью до 0.0005. Сделал как показано ниже. Работает. //__________________________Округление Upr (float) с точностью до 0,0005 S = round (Upr * 10000); // Пример 1,925619*10000 = 19256,19 => S=19256 byte t = S % 10; // t=6 if (t < 3) { t = 0; } if (t > 7) { t = 10; } if (t >= 3 && t <= 7) { t = 5; } S = S / 10 * 10 + t; // t=5, S= 19250 + 5 Upr = S / 10000.0; // Upr = 1.9255
Однако, теперь понадобилось округление с точностью до 0,0002.
Подскажите пожалуйста более гуманный способ округления. Может быть есть покороче алгоритмы?
long SS=(float)UPR*5000;
float S=SS/5000;
И все лишнее отпадет.
Строка 05 это делает. У меня задача не убрать лишнее - это не проблема, а округлить до заданной точности.
Если точность 0.0005, то число
1,925619 превращается, очевидно, в
1.9255.
А надо еще до 0.0002 округлять, т.е. то же число
1,925619 должно преобразоваться в 1.9256, а число 1.92571 должно округиться до 1.9258.
Ну так добавляете половину младшего разряда:
long SS=(float)UPR*5000 + 0.5;
И что? Опять отбрасывание. Причем еще и ошибаться будет. А округление-то с точностью до заданного числа где?
И что? Опять отбрасывание. Причем еще и ошибаться будет. А округление-то с точностью до заданного числа где?
Учите математику. Без знания математики в программировании сложно. А раскладывать вам математическое доказательство. Ну-ну. Ищите идиота в другом месте.
Примерно так, если чисто по логике.
Но на самом деле, всё не так просто. Мы пытаемся округлить до десятичных знаков, но на самом деле float-числа хранятся в двоичном виде. То есть, после нашего округления они будут округлены ещё раз - до ближайшего двоичного значения. Это значит, потом, при выводе в десятичном виде, опять могут появиться лишние знаки.
Не знаю, понятно ли написал - но в общем, такое округление правильно работает на не слишком больших числах, и не слишком маленьких. Как и алгоритм из стартового поста, насколько я понимаю.
Datak, спасибо, что напомнили об особенностях вещественных чисел, но другого округления все равно нет, так что приходится мириться со всеми недостатками и несовершенствами.
Вы путаете округление и формат данных. А это разные вещи.
Вероятно я неправильно задал тему. Прошу прощения. Мне нужно получить в заданном разряде после запятой так сказать определенную дискретность. Т.е число в заданном разяре должно быть кратным заданному.
Поясню на простом примере (точность 0.5) c меньшим кол-вом цифр:
Входящее число (float) число на выходе
1.0 1.0
1.1 1.0
1.2 1.0
1.3 1.5
1.4 1.5
1.5 1.5
1.6 1.5
1.7 1.5
1.8 2.0
1.9 2.0
2.0 2.0
Кусок кода в начальном сообщении прекрасно справляется с этой задачей без ошибок.
Однако, как я писал теперь нужно сделать младший заданный разряд кратным 2-ке, а конкретно 0.0002.
Можно решить задачу так же как я сделал для пятерки, анализируя младший заданный разряд числа.
Однако может быть как-то можно покороче? Чтобы не плодить if.
Вы путаете округление и формат данных. А это разные вещи.
Я не путаю вещи, я просто путаюсь в показаниях. :)
То есть, не умею достаточно чётко объяснять, о чём и предупреждал.
Да, строго говоря, ошибка из-за перевода между двоичной/десятичной системами, и ошибка из-за ограниченного размера мантиссы float-числа - это разные вещи, и они обе вносят погрешность в конечный результат.
И, раз уж зашёл, поправлю самого себя. "Слишком большие" и "слишком маленькие" - это не совсем правильно. Тут важно не значение, а именно точность числа - то есть, количество значащих цифр - не важно, до запятой или после.