LINUX.ORG.RU

Как наиболее Ъ занулить последние байты мантиссы для double и float?

 


0

3

Сабж. Нужно для того, что бы убрать влияние накопившейся машинной ошибки при сравнении чисел. Ключевое требование - должно работать быстро. Тупое решение в лоб

inline bool less(double x, double y){ 
    *((long*)&x) &= 0xFFFFFFFFFFFF0000; 
    *((long*)&y) &= 0xFFFFFFFFFFFF0000; 
    return x<y; 
}
выдает при компиляции
warning: dereferencing type-punned pointer will break strict-aliasing rules
че то мне оно не нравится....

★★★★★

double x

(long*)&x

Фу таким быть.

убрать влияние накопившейся машинной ошибки

Ты его не уберёшь, только добавишь ещё.

anonymous
()
Ответ на: комментарий от x0r

ворнинги отключи.

Можно еще голову под подушку спрятать.

а отнять это не достаточно быстро?

Нет, тем более что одним вычитанием там не обойдешься.

AIv ★★★★★
() автор топика
#include <stdio.h>


double x=55.46846486;
double y=77.96849684;


void foo(double *x , double *y)
{ 
    *((long*)&x) &= 0xFFFFFFFFFFFF0000; 
    *((long*)&y) &= 0xFFFFFFFFFFFF0000; 
    x<y;
};


int main()
{

  foo(&x,&y);
  printf("x=%f\ny=%f\n",x,y);

  return 0;
};
Dron ★★★★★
()
Последнее исправление: Dron (всего исправлений: 1)
Ответ на: комментарий от ziemin

Спасибо КО. Только сравниваемые числа могут быть порядка десять в дцатой (или десять в минус дцатой). Причем тут единица?

AIv ★★★★★
() автор топика
Ответ на: комментарий от AIv

Что работает? Сравнение? Так оно на определённой выборке и в виде (long)x < long(y) будет работать! А вот ошибки никуда не денутся.

anonymous
()
Ответ на: комментарий от anonymous

Ошибка это неизбежное зло. Мне нужно, что бы числа у которых различаются последние 16 бит мантиссы (за счет ошибки) считались при сравнении равными.

AIv ★★★★★
() автор топика
Ответ на: комментарий от x0r

Я конечно понимаю, что ТС идиот, но таки не видеть отличий между (long)double и (long*)(double*) - это надо постараться.

anonymous
()

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

/0

зря ты так делаешь.

drBatty ★★
()
Ответ на: комментарий от mashina

Что такое A, B, s? В С нету операции **, побитовый сдвиг не поддерживается для плавающей точки.

AIv ★★★★★
() автор топика
Ответ на: комментарий от drBatty

зря ты так делаешь.

Да, ЛОР не то что не торт - ЛОР вообще скатился хрен-знает-во-что. Я что, где то у кого то спрашивал делать мне так или не делать?

А мнение анонимуса насчет того идиот я или нет меня вообще не интересует.

AIv ★★★★★
() автор топика
Ответ на: комментарий от anonymous

Куда добавляю? Ничего, что less принимает аргуметы по значению? Блин, анонимусы тоже пошли какие то тупые...

AIv ★★★★★
() автор топика
Ответ на: комментарий от AIv

Ошибка это неизбежное зло.

ошибка — не зло. Это просто погрешность вычислений.

считались при сравнении равными.

зачем ты сравниваешь double?

drBatty ★★
()
Ответ на: комментарий от AIv

Подумай немножко, прежде чем бред писать. Очевидно, что добавляешь только при сравнении (и они дальше не лезут), но тем самым делаешь сравнение ошибочным.

anonymous
()
Ответ на: комментарий от anonymous

у него все в скобках с префиксным разыменованием, фактически double к long

x0r ★★★★★
()
Ответ на: комментарий от drBatty

зачем ты сравниваешь double?

Потому что мне нужно сравнивать double. Есть альтернативы?

AIv ★★★★★
() автор топика
Ответ на: комментарий от anonymous

Я знаю, что у меня последние 16 бит невалидные, а актуальные значение (которое должно сравниваться) лежит в первых скольки-то-там битах. Зачем мне сравнивать числа с учетом заведомо ошибочного хвоста? Кто из наc пишет бред?

AIv ★★★★★
() автор топика
Ответ на: комментарий от anonymous

Я уже боюся, не заразны ли идеи прокодера с фихед пойнт... как бы не началось.

AIv ★★★★★
() автор топика
Ответ на: комментарий от bormant

О, спасибо... про union я и забыл;-(

AIv ★★★★★
() автор топика
Ответ на: комментарий от AIv

Что такое A, B, s?

что, мне капитанить обязательно? A и B операнды сравнения, s желаемый порядок загрубления сравнения. Второй сдвиг просто на s, не на (2**s). Т.е. ддя твоих желаемых 16и будет примерно 36.

побитовый сдвиг не поддерживается для плавающей точки.

man ldexp(), fpu это делать умеет.

ещё от знака нужно избавиться у A и B

mashina ★★★★★
()
Ответ на: комментарий от AIv
#include <stdio.h>

const double E = 1.0/(1000*1000*1000);
const double E2 = 2.0/(1000*1000*1000);

inline bool less(double x, double y) {
    *((long*)&x) &= 0xFFFFFFFFFFFF0000;
    *((long*)&y) &= 0xFFFFFFFFFFFF0000;
    return x<y;
}

inline bool eq(double x, double y) {
    return x-y < E && y-x < E;
}

void compare(double x, double y) {
    printf("%.16f %s %.16f\n", x, less(x, y) ? "<" : (less(y, x) ? ">" : "="), y);
    printf("%.16f %s %.16f\n", x, eq(x, y) ? "=" : "!=", y);
}

int main() {
    double x = 1.0+E*2-E2;
    double y = 1.0;
    compare(x, y);
}
anonymous
()
Ответ на: комментарий от AIv

Есть нюанс - это будет гораздо медленней, чем снести последние биты.

хз как это заоптимизирует компилятор, лень сравнивать. Но по крайней мере этот вариант правильный в отличие от твоего подхода. Ты же не знаешь какой размер будет у типа double - с/с++, афаик, не обещают что это будет double из ieee754

mashina ★★★★★
()
Ответ на: комментарий от anonymous

Черт... да, это убедительно, я ступил;-( Спасибо!

AIv ★★★★★
() автор топика
Ответ на: комментарий от mashina

Ну, под целевую архитектуру я размеры всех типов знаю... но анонимус тут привел пример когда нулить хвост мантиссы низя;-(

AIv ★★★★★
() автор топика
Ответ на: комментарий от mashina

В общем как то так вышло:

inline bool less(double x, double y) {
	int px, py; frexp(x, &px); frexp(y, &py);	
    return y-x >= ldexp(1., (px<py?px:py)-40);
}
Еще раз спасибо Анонимусу!

AIv ★★★★★
() автор топика
Ответ на: комментарий от AIv

Прочит тему - так и не понял, что за фигня - вы long=4байта, double=8 байт, приводя указатель вы используете первые 4 байта от double.

Не проще умножить->каст->поделить.

pulo
()
Ответ на: комментарий от nikitos

Y больше X потому что флюгер прибит гвоздями и ветер дует в заданную сторону?

Потому что числовая прямая имеет обычно стрелочку со стороны положительных чисел (помните как в школе рисовали)?

AIv ★★★★★
() автор топика
Ответ на: комментарий от AIv

это всё отлично, посмотрев ещё раз на код, но всё же, как мне пауки в голове говорят, >= надо поменять на >.

nikitos ★★★
()
Ответ на: комментарий от AIv

С удивлением узнал что на рабочей машине стоит 32битная убунта:-D

А так да, long 64bit, хотя сам стараюсь везде писать uint64_t или int64_t если нужно именно 64

pulo
()
Ответ на: комментарий от AIv

Вот интересно, случай, когда мантиссы вида (укороченные)

1100 0000 0000 0001

1011 1111 1111 1111

ТС не волнует? То есть разница чисел в пару единиц младшего разряда, но при этом различаются старшие разряды. При обнулении младших бит разница будет возрастать, а не уменьшаться.

Elyas ★★★★★
()
Последнее исправление: Elyas (всего исправлений: 1)
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.