Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Общие вопросы > Как округлить число до N-го знака после запятой...


Автор: chipset 28.3.2005, 03:14
 Округление чисел
Используя функцию, приведённую ниже, можно округлить число типа double с требуемой точностью. Округлять можно по двум правилам:
1) то, чему нас учили в школе: если округляем до двух знаков после запятой, то сотые доли либо увеличиваются на 1, либо остаются без изменений - в зависимости от значений тысячных (если 4 тысячных - то оставляем сотые как есть, если больше 5-ти - увеличиваем сотые на 1, если 5 - то смотрим десятитысячные), все цифры правее сотых - отбрасываются;
2) простое отбрасывание всех цифр, правее указанной (если округляем до сотых, то тысячные и т.п. -- отбрасываются).

Для первого варианта округления, параметр nType должен быть равен ROUND_UP, для второго варианта - ROUND_TRIM. Параметр nPrecis задаёт количество знаков после запятой (номер цифры после запятой, до которой округляется число).
Код
#include "math.h"

#define ROUND_UP            1
#define ROUND_TRIM         2

const double Two=2, Five=5, Ten=10;
const double MaxPrecis=pow(10, 16);


[b]double Round(double Value, int nPrecis, int nType=ROUND_UP)[/b]
{
      if(nPrecis > 16 || !nPrecis) return Value;
      if(Value == 0) return Value;

      short wTmp;
    
      _asm
      {
            finit
            fstcw     wTmp
            mov     ax, wTmp      
            or        ax, 0000110000000000b   // RC=11 - trimming
            cmp      nType, ROUND_UP
            jne       m1
            and      ax, 1111001111111111b   // RC=00 - upper
m1:      mov      wTmp, ax
            fldcw    wTmp      
  
            fld         Value
            mov      ecx, nPrecis
            push      ecx
m2:      fmul      Ten
            loop      m2
  
            frndint
  
            pop      ecx
m3:      fdiv      Ten
            loop      m3
            fstp      Value
      }

      return Value;
}


Проверка "целое ли число"
Следующая функция возвращает true, если число целое (не имеет знаков правее запятой), и  false -- если дробное. Отличие данной функции от простого выражения   ((double)(int) fValue) ==  fValue ? true:false  состоит в том, что она позволяет работать с числами, бОльшими чем позволяет формат  int  (например, не зная точно, больше число по модулю, чем 2 триллиона, или нет - сложно определить, сработает ли выражение приведенное выше, требуется ещё рад проверок).

Итак, функция для проверки, целое или дробное число Value:
Код
#include "math.h"

[b]bool IsRounded(double Value)[/b]
{
      bool bResult = true; 
      short wTmp;
      _asm
      {
            finit
  
            fstcw      wTmp
            mov       ax, wTmp      
            or          ax, 0010110000000000b   // RC=11 - trimming, PC=11 - max precis
            mov       wTmp, ax
            fldcw       wTmp

            fld          Value
            fld          Value
            frndint
            fsub
            fxam

            fstsw      ax
            sahf
            je           end
            mov      bResult, 0
            jmp        end
  
end:      finit
      }

      return bResult;
}
 

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)