Перейти к содержанию
    

Ошибка конверсии (unsigned int) double ?

Вычисляю sin табличным методом

(LPC2478 в среде Keil 4.23)

 

кусок кода

 

....
#define Tabl_acos 0x80000000
...
...
double tsin (double arg)
{
double argout;
unsigned int *adr;

    adr = (unsigned int *)((unsigned int)Tabl_sin + (unsigned int)(fabs(arg)*400));
    argout = *(double *)adr;
    return (argout);
}

 

Указатель adr при вычислении имеет совершенно фантастическое значение !

 

А в коде ниже (unsigned int)fabs(arg)*400 работает правильно, но теряется точность, поскольку приведение к uint происходит до умножения на 400.

 

....
#define Tabl_acos 0x80000000
...
...
double tsin (double arg)
{
double argout;
unsigned int *adr;

    adr = (unsigned int *)((unsigned int)Tabl_sin + (unsigned int)fabs(arg)*400);
    argout = *(double *)adr;
    return (argout);
}

 

Пробовал разные ключи компилятора - не помогает

Заметил, что ошибка возникает, когда значение arg*400 превышает 255.

 

Глюк компилятора?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Указатель adr при вычислении имеет совершенно фантастическое значение !

"Фантастическое значение"? А это хорошо или плохо?

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

К тому же у вас как-то подозрительно вычисляется адрес. Он ведь должен быть кратен 8 (указатель на double). При этом совсем нигде не видно, где эта кратность обеспечивается.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

400ULL

Ага, щас. Вообще-то 400 перед умножением автоматически приводится к double. Так что ULL ничего не изменит.

Скорее уж 400.0, чтобы убрать неявное приведение типа.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Ага, щас. Вообще-то 400 перед умножением автоматически приводится к double. Так что ULL ничего не изменит.

Скорее уж 400.0, чтобы убрать неявное приведение типа.

Не обратил внимание, что там double. Да, 400.0

 

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Не обратил внимание, что там double. Да, 400.0

Только это всё равно ничего не изменит.

У меня есть версия. Возможно, стек не выравнен по границе 8 байт, и из-за этого не работает умножение double*double.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Сделал втупую

 

  value = arccos (0);     // result = 90
  value = arccos (0.465); // result = 62.289
  value = arccos (0.5);   // result = 60
  value = arccos (0.563); // result = -4967.265 (incorrect!)
  value = arccos (0.564); // result = -4967.265 (incorrect!)
  value = arccos (0.565); // result = -4967.265 (incorrect!)
  value = arccos (0.566); // result = 0 (incorrect!)
  value = arccos (0.567); // result = -4967.265 (incorrect!)
  value = arccos (0.568); // result = -4967.265 (incorrect!)
  value = arccos (0.569); // result = 0 (incorrect!)
  value = arccos (0.57);  // result = 0 (incorrect!)
  value = arccos (0.58);  // result = 54.549
  value = arccos (0.59);  // result = 53.842
  value = arccos (1);     // result = 0

 

результат поставил вообще в тупик ....

 

таблицу проверял 100 раз

выводил на экран значения от 0.5 до 0.6

Возможно в других диапазонах тоже самое

 

 

Только это всё равно ничего не изменит.

У меня есть версия. Возможно, стек не выравнен по границе 8 байт, и из-за этого не работает умножение double*double.

 

А как стек выровнять? Добавить __align(32)?

Изменено пользователем ZSN1

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Таблица зашита во внешнюю flash

 

/*
const double __at(0x80000000) Tabl_acos[400] = 
{
9.00000000000000E+0001, 8.99942704220391E+0001, 8.99885408440210E+0001, 8.99828112658882E+0001, 8.99770816875836E+0001, 8.99713521090498E+0001, 8.99656225302295E+0001, 8.99598929510654E+0001,
......
2.29198399677718E+0000, 2.14393684184771E+0000, 1.98488327611931E+0000, 1.81192713807401E+0000, 1.62062339292405E+0000, 1.40348933094521E+0000, 1.14593468971431E+0000, 8.10291437065700E-0001, 0.00000000000000E+0000 };
*/
#define Tabl_acos 0x80000000

 

Чтоб не перепрошивалась каждый раз при перепрошивке, ее закоментил и в проге поставил дефайн

 

 

Чёй-то 32? С какой радости?

__allign (64)

 

 

Кстати, если разкоментить таблицу, то все работает

double arccos (double arg)
{
double argout;
    argout = Tabl_acos[(unsigned int)(fabs(arg*400))];
    return (argout);
}

Изменено пользователем ZSN1

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Кстати, если разкоментить таблицу, то все работает

:08:

И код уже поменялся, и преобразование типов вроде бы ни при чём.

За вами не уследишь: советуешь что-то, а оно уже не актуально, всё поменялось :biggrin:

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

:08:

И код уже поменялся, и преобразование типов вроде бы ни при чём.

За вами не уследишь: советуешь что-то, а оно уже не актуально, всё поменялось :biggrin:

И это правильно - если чтото не так то нужно менять B) потом может по свободе докопаюсь ...

Изменено пользователем ZSN1

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

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

Гость
К сожалению, ваш контент содержит запрещённые слова. Пожалуйста, отредактируйте контент, чтобы удалить выделенные ниже слова.
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...