реклама на сайте
подробности

 
 
 
Reply to this topicStart new topic
> Ошибка конверсии (unsigned int) double ?
ZSN1
сообщение Aug 20 2015, 06:35
Сообщение #1





Группа: Новичок
Сообщений: 9
Регистрация: 20-08-15
Пользователь №: 88 062



Вычисляю 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.

Глюк компилятора?
Go to the top of the page
 
+Quote Post
scifi
сообщение Aug 20 2015, 07:15
Сообщение #2


Гуру
******

Группа: Свой
Сообщений: 3 020
Регистрация: 7-02-07
Пользователь №: 25 136



Цитата(ZSN1 @ Aug 20 2015, 09:35) *
Указатель adr при вычислении имеет совершенно фантастическое значение !

"Фантастическое значение"? А это хорошо или плохо?
Если есть сомнения в правильности вычислений, разбейте вычисления на элементарные операции и контролируйте результаты на каждом шагу.
К тому же у вас как-то подозрительно вычисляется адрес. Он ведь должен быть кратен 8 (указатель на double). При этом совсем нигде не видно, где эта кратность обеспечивается.
Go to the top of the page
 
+Quote Post
zltigo
сообщение Aug 20 2015, 07:57
Сообщение #3


Гуру
******

Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244



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

Нет.
400ULL


--------------------
Feci, quod potui, faciant meliora potentes
Go to the top of the page
 
+Quote Post
scifi
сообщение Aug 20 2015, 08:04
Сообщение #4


Гуру
******

Группа: Свой
Сообщений: 3 020
Регистрация: 7-02-07
Пользователь №: 25 136



Цитата(zltigo @ Aug 20 2015, 10:57) *
400ULL

Ага, щас. Вообще-то 400 перед умножением автоматически приводится к double. Так что ULL ничего не изменит.
Скорее уж 400.0, чтобы убрать неявное приведение типа.
Go to the top of the page
 
+Quote Post
zltigo
сообщение Aug 20 2015, 08:17
Сообщение #5


Гуру
******

Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244



QUOTE (scifi @ Aug 20 2015, 11:04) *
Ага, щас. Вообще-то 400 перед умножением автоматически приводится к double. Так что ULL ничего не изменит.
Скорее уж 400.0, чтобы убрать неявное приведение типа.

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



--------------------
Feci, quod potui, faciant meliora potentes
Go to the top of the page
 
+Quote Post
scifi
сообщение Aug 20 2015, 08:21
Сообщение #6


Гуру
******

Группа: Свой
Сообщений: 3 020
Регистрация: 7-02-07
Пользователь №: 25 136



Цитата(zltigo @ Aug 20 2015, 11:17) *
Не обратил внимание, что там double. Да, 400.0

Только это всё равно ничего не изменит.
У меня есть версия. Возможно, стек не выравнен по границе 8 байт, и из-за этого не работает умножение double*double.
Go to the top of the page
 
+Quote Post
ZSN1
сообщение Aug 20 2015, 10:49
Сообщение #7





Группа: Новичок
Сообщений: 9
Регистрация: 20-08-15
Пользователь №: 88 062



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

Код
  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
Возможно в других диапазонах тоже самое


Цитата(scifi @ Aug 20 2015, 08:21) *
Только это всё равно ничего не изменит.
У меня есть версия. Возможно, стек не выравнен по границе 8 байт, и из-за этого не работает умножение double*double.


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

Сообщение отредактировал ZSN1 - Aug 20 2015, 10:51
Go to the top of the page
 
+Quote Post
Obam
сообщение Aug 20 2015, 10:57
Сообщение #8


Знающий
****

Группа: Участник
Сообщений: 756
Регистрация: 14-11-14
Пользователь №: 83 663



Цитата(ZSN1 @ Aug 20 2015, 14:49) *
А как стек выровнять? Добавить __align(32)?


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


--------------------
Пролетарий умственного труда.
Go to the top of the page
 
+Quote Post
ZSN1
сообщение Aug 20 2015, 11:03
Сообщение #9





Группа: Новичок
Сообщений: 9
Регистрация: 20-08-15
Пользователь №: 88 062



Таблица зашита во внешнюю 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


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


Цитата(Obam @ Aug 20 2015, 10:57) *
Чёй-то 32? С какой радости?

__allign (64)


Кстати, если разкоментить таблицу, то все работает
Код
double arccos (double arg)
{
double argout;
    argout = Tabl_acos[(unsigned int)(fabs(arg*400))];
    return (argout);
}


Сообщение отредактировал ZSN1 - Aug 20 2015, 11:04
Go to the top of the page
 
+Quote Post
Obam
сообщение Aug 20 2015, 11:13
Сообщение #10


Знающий
****

Группа: Участник
Сообщений: 756
Регистрация: 14-11-14
Пользователь №: 83 663



Цитата(ZSN1 @ Aug 20 2015, 15:03) *
__allign (64)


http://www.keil.com/support/man/docs/armcc...ef_babdfecc.htm


--------------------
Пролетарий умственного труда.
Go to the top of the page
 
+Quote Post
scifi
сообщение Aug 20 2015, 11:34
Сообщение #11


Гуру
******

Группа: Свой
Сообщений: 3 020
Регистрация: 7-02-07
Пользователь №: 25 136



Цитата(ZSN1 @ Aug 20 2015, 14:03) *
Кстати, если разкоментить таблицу, то все работает

08.gif
И код уже поменялся, и преобразование типов вроде бы ни при чём.
За вами не уследишь: советуешь что-то, а оно уже не актуально, всё поменялось biggrin.gif
Go to the top of the page
 
+Quote Post
ZSN1
сообщение Aug 20 2015, 11:37
Сообщение #12





Группа: Новичок
Сообщений: 9
Регистрация: 20-08-15
Пользователь №: 88 062



Цитата(scifi @ Aug 20 2015, 11:34) *
08.gif
И код уже поменялся, и преобразование типов вроде бы ни при чём.
За вами не уследишь: советуешь что-то, а оно уже не актуально, всё поменялось biggrin.gif

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

Сообщение отредактировал ZSN1 - Aug 20 2015, 11:38
Go to the top of the page
 
+Quote Post

Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 19th July 2025 - 16:39
Рейтинг@Mail.ru


Страница сгенерированна за 0.01467 секунд с 7
ELECTRONIX ©2004-2016