округление младшего разряда
От: Аноним  
Дата: 07.07.08 13:11
Оценка:
есть
double v;

нужно округлить обнулив все разряды, начиная от 10^-3,
как обычно это делают, учитывая что "v" может быть отрицательной.
Re: округление младшего разряда
От: Were  
Дата: 07.07.08 13:53
Оценка:
Здравствуйте, Аноним, Вы писали:

А>есть

А>
А>double v;
А>

А>нужно округлить обнулив все разряды, начиная от 10^-3,
А>как обычно это делают, учитывая что "v" может быть отрицательной.


double mean = 100;
v = ( v < 0 ? ceil( v * mean ) : floor( v * mean )) / mean;
Re[2]: округление младшего разряда
От: Аноним  
Дата: 07.07.08 13:57
Оценка:
Здравствуйте, Were, Вы писали:

W>Здравствуйте, Аноним, Вы писали:


А>>есть

А>>
А>>double v;
А>>

А>>нужно округлить обнулив все разряды, начиная от 10^-3,
А>>как обычно это делают, учитывая что "v" может быть отрицательной.


W>
W>double mean = 100;
W>v = ( v < 0 ? ceil( v * mean ) : floor( v * mean )) / mean;
W>


да, но здесь используется умножение и деление,
а нельзя обойтись без них, скажем прибавить или отнять 0.005,
а потом просто как-нибудь обнулить то что не нужно
Re[3]: округление младшего разряда
От: Кодт Россия  
Дата: 07.07.08 15:36
Оценка: +1
Здравствуйте, <Аноним>, Вы писали:

А>да, но здесь используется умножение и деление,

А>а нельзя обойтись без них, скажем прибавить или отнять 0.005,
А>а потом просто как-нибудь обнулить то что не нужно

Нужно понимать устройство плавающей арифметики. Если коротко, то: нет, "просто как-нибудь" нельзя.
А ещё замечу, что 0.005 непредставимо в double, поэтому обязательно возникнут погрешности. Где эти погрешности вылезут — нужно смотреть на твои дальнейшие действия.

Если же тебе просто нужно вывести в строку (или на экран) — то смотри спецификацию форматов у printf и манипуляторы вывода у iostream'ов (setw, setprecision).
... << RSDN@Home 1.2.0 alpha rev. 655>>
Перекуём баги на фичи!
Re: округление младшего разряда
От: Аноним  
Дата: 08.07.08 03:42
Оценка:
Здравствуйте, Аноним, Вы писали:

А>нужно округлить обнулив все разряды, начиная от 10^-3,

А>как обычно это делают, учитывая что "v" может быть отрицательной.

Для округления чисел с плавающей точкой, ни в коем случае
нельзя использовать деление, я бы рекомендовал перейти в
область строковой конверсии. Вы берете число
double dValue = 345.6763880009999
Int64 nValue = (Int64)(dValue * 10000); // множитель точности числа
string sVal = DoubleToString(nValue);
эта функция должна выдать строку типа 3456764(5).
затем конвертируешь ее обратно в добл
без деления.
Re[2]: округление младшего разряда
От: CreatorCray  
Дата: 08.07.08 05:37
Оценка:
Здравствуйте, <Аноним>, Вы писали:

А>Для округления чисел с плавающей точкой, ни в коем случае

А>нельзя использовать деление
А>А>string sVal = DoubleToString(nValue);
А>затем конвертируешь ее обратно в добл без деления.
А вот в процессе конвертации деления у тебя не повылазят?
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[2]: округление младшего разряда
От: Аноним  
Дата: 08.07.08 06:16
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Здравствуйте, Аноним, Вы писали:


А>>нужно округлить обнулив все разряды, начиная от 10^-3,

А>>как обычно это делают, учитывая что "v" может быть отрицательной.

А>Для округления чисел с плавающей точкой, ни в коем случае

А>нельзя использовать деление, я бы рекомендовал перейти в
А>область строковой конверсии. Вы берете число
А>double dValue = 345.6763880009999
А>Int64 nValue = (Int64)(dValue * 10000); // множитель точности числа
А>string sVal = DoubleToString(nValue);
А>эта функция должна выдать строку типа 3456764(5).
А>затем конвертируешь ее обратно в добл
А>без деления.

шутка?
мне кажется все это будет работать намного дольше, чем деление и умножение?
Re[2]: округление младшего разряда
От: Were  
Дата: 08.07.08 06:27
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Для округления чисел с плавающей точкой, ни в коем случае

А>нельзя использовать деление, я бы рекомендовал перейти в
А>область строковой конверсии. Вы берете число
А>double dValue = 345.6763880009999
А>Int64 nValue = (Int64)(dValue * 10000); // множитель точности числа
Точности int64 может не хватить для представления double. Например когда dValue = 1e100;

А>string sVal = DoubleToString(nValue);

Не знаю, что за функция, но во-первых ее аргумент не double, а int64, а во-вторых для перевода числа в строку с десятичной записью нужно использовать не одно деление )

А>эта функция должна выдать строку типа 3456764(5).

А>затем конвертируешь ее обратно в добл
А>без деления.

Если не нравится деление можно умножать на обратную величину точности, которую посчитать заранее.
Re[4]: округление младшего разряда
От: Аноним  
Дата: 08.07.08 06:51
Оценка:
Здравствуйте, Кодт, Вы писали:

К>Здравствуйте, <Аноним>, Вы писали:


А>>да, но здесь используется умножение и деление,

А>>а нельзя обойтись без них, скажем прибавить или отнять 0.005,
А>>а потом просто как-нибудь обнулить то что не нужно

К>Нужно понимать устройство плавающей арифметики. Если коротко, то: нет, "просто как-нибудь" нельзя.

К>А ещё замечу, что 0.005 непредставимо в double, поэтому обязательно возникнут погрешности. Где эти погрешности вылезут — нужно смотреть на твои дальнейшие действия.

Исходная задача, есть итерационный алгоритм, и он накапливает погрешность,
надо время от времени можно и на каждом шаге, отбрасывать ненужные знаки после запятой,
я так посчитал, что это начиная от скажем 10^-3, в принципе и 2^-10 меня тоже устроит.

если требования к округлению сместить с десятичной системы в двоичную это поможет
предложить более эффективный алгоритм округления?
Re[5]: округление младшего разряда
От: Кодт Россия  
Дата: 08.07.08 09:51
Оценка:
Здравствуйте, <Аноним>, Вы писали:

А>Исходная задача, есть итерационный алгоритм, и он накапливает погрешность,

А>надо время от времени можно и на каждом шаге, отбрасывать ненужные знаки после запятой,

Но ведь округление только увеличивает погрешность?
А кстати, что за формула?

А>я так посчитал, что это начиная от скажем 10^-3, в принципе и 2^-10 меня тоже устроит.

А>если требования к округлению сместить с десятичной системы в двоичную это поможет предложить более эффективный алгоритм округления?

В принципе, да.
Начиная с того, что можно руками распотрошить двоичное представление числа и обнулить соответствующие разряды мантиссы (в зависимости от порядка, естественно).
Либо похимичить с frexp() / ldexp(). С ходу не скажу формулу.
... << RSDN@Home 1.2.0 alpha rev. 655>>
Перекуём баги на фичи!
Re[5]: округление младшего разряда
От: Were  
Дата: 08.07.08 10:40
Оценка:
Здравствуйте, Аноним, Вы писали:

А>если требования к округлению сместить с десятичной системы в двоичную это поможет

А>предложить более эффективный алгоритм округления?

Ага, примерно такой. За ошибки не отвечаю

void bin_truncate( double &in, unsigned bits )
{
#define EXP_BIAS 1022
#define MANTISSA_HIGH_BITS 20
#define MANTISSA_BITS 52
#define SIGN_MASK 0x7fffffff

    unsigned *p = (unsigned*)&in;
    int exp = (( p[1] & SIGN_MASK ) >> MANTISSA_HIGH_BITS ) - 
        EXP_BIAS + bits;

    if ( exp <= 0 )
        in = 0;
    if ( exp < MANTISSA_HIGH_BITS )
    {
        p[0] = 0;
        p[1] &= (unsigned)-1 << ( MANTISSA_HIGH_BITS - exp );
    }
    else if ( exp < MANTISSA_BITS )
        p[0] &= (unsigned)-1 << ( MANTISSA_BITS - exp );

#undef EXP_BIAS
#undef MANTISSA_HIGH_BITS
#undef MANTISSA_BITS
#undef SIGN_MASK
}
Re[6]: округление младшего разряда
От: Аноним  
Дата: 08.07.08 10:58
Оценка:
Здравствуйте, Кодт, Вы писали:

К>Здравствуйте, <Аноним>, Вы писали:


А>>Исходная задача, есть итерационный алгоритм, и он накапливает погрешность,

А>>надо время от времени можно и на каждом шаге, отбрасывать ненужные знаки после запятой,

К>Но ведь округление только увеличивает погрешность?

К>А кстати, что за формула?

цифровой фильтр, сглаживает экспериментальные данные, точность в 10^-3 недостижима из-за инструментальной погрешности,
формула довольно большая, типа
x_вспомогательная_1 = сумма произведений
x_вспомогательная_2 = сумма произведений
x_результат = ...

те кто спроектировали этот фильтр (подобрали формулу и коэфиценты)
высказали предположение что фильтр будет накапливать погрешность,
и хорошо бы незначимые разряды обнулять.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.