Цитата Сообщение от kondor3000 Посмотреть сообщение
Сделал проще, ввёл 2 точки, где не работало 1 и -1, зато вычисление намного быстрее, точнее и цикл маленький
Скрытый текст:
Код:
function SIN_Rad: real ; //имя функции и тип данных выхода
    var_input 
       X: real ;  //входная переменная 
    end_var  
    var //объявление локальных переменных
       Zn : real ; 
       Pi : real:=3.1415927 ; 
       a,b: real ; 
    end_var
    
       Zn:=pow(-1,bool_to_real(EXTRACT(real_to_udint((abs(X))/Pi),0) XOR not (X>0))); 
       a:=(abs(X)/Pi - udint_to_real(real_to_udint(abs(X)/Pi)))*Pi ;
       b:=(Pi-a) * (bool_to_real(a>1.5707964))+a* bool_to_real(not(a>=1.5707964)) ;  //   1,5707964 
       if x=1.5707964  or x=7.853982 then
          SIN_Rad:=1.0; 
       elsif x=-1.5707964 or x=4.712389 then
          SIN_Rad:=-1.0; 
       else   
          SIN_Rad:=((pow(b,9)/362880 + (((b-(pow(b,3)/6)) +pow(b,5)/120)- pow(b,7)/5040))-pow(b,11)/39916800)*Zn ;
      end_if
end_function
Кстати, при последовательном вычислении членов ряда ошибка не возникает. Значение функций SIN_Rad и SIN_Rad2 практически совпадают. По данным fSUB разность 5.96E-8 отмечается лишь на некоторых углах (+/- 50, 245, 255 … - проверял через 5 градусов)). Извиняюсь за грубое редактирование (только для примера).
Скрытый текст:
Код:
function SIN_Rad2: real ; //имя функции и тип данных выхода
    var_input 
       X: real ;  //входная переменная 
    end_var  
    var //объявление локальных переменных
       Zn : real ; 
       Pi : real:=3.1415927 ; 
       a,b: real ; 
          i : udint;              (* переменная цикла *) 
    end_var
 
       Zn:=pow(-1,bool_to_real(EXTRACT(real_to_udint((abs(X))/Pi),0) XOR not (X>0))); 
       a:=(abs(X)/Pi - udint_to_real(real_to_udint(abs(X)/Pi)))*Pi ;
       b:=(Pi-a) * (bool_to_real(a>1.5707964))+a* bool_to_real(not(a>=1.5707964)) ;  //   1,5707964 
    (*      
       if x=1.5707964  or x=7.853982 then
          SIN_Rad2:=1.0; 
       elsif x=-1.5707964 or x=4.712389 then
          SIN_Rad2:=-1.0; 
       else   
          SIN_Rad2:=((pow(b,9)/362880 + (((b-(pow(b,3)/6)) +pow(b,5)/120)- pow(b,7)/5040))-pow(b,11)/39916800)*Zn ;
      end_if
    *)
    
  // Вычисление степенного ряда Тейлора:    
  a:=b;    (* 1-й член разложения *)
  SIN_Rad2:= b; (* = 1-му члену разложения *)
  b:=b*b;  (* далее квадрат b *)
  for i := 3 to 11 by 2 do
    a:=a*b / udint_to_real(i * (i-1));(* очередной член разложения *)
    SIN_Rad2:=a-SIN_Rad2;
  end_for
   SIN_Rad2:=-SIN_Rad2*Zn;  
   
end_function