Visual Basic, .NET, ASP, VBScript
 

   
   
     

Форум - Power Basic

Страница: 1 |

 

  Вопрос: Передача в функцию переменной произвольного типа Добавлено: 22.08.06 10:13  

Автор вопроса:  alex
Как можно реализовать передачу в функцию произвольного типа данных? Variant использовать не хочется, т.к. считается, что он слишком тормозной.
 
Может, можно реализовать как-то через указатели?
Нужно, чтобы функция могла принимать переменные разных типов.

Function Test (byVal p as WORD|DWORD|DOUBLE) AS DOUBLE
   Function=Sin(p)
End Function

Ответить

  Ответы Всего ответов: 8  

Номер ответа: 1
Автор ответа:
 Alex



Вопросов: 7
Ответов: 73
 Профиль | | #1 Добавлено: 22.08.06 10:59
Если ты используешь только числа, тогда используй тип DOUBLE и все будет в поряде. Но при этом всегда нужен byVal чтоб не было матюков насчет несовместимости типов данных. Пример :

Function Test (byVal p As DOUBLE) AS DOUBLE
   Test=Sin(p)
End Function

Ответить

Номер ответа: 2
Автор ответа:
 alex



Вопросов: 84
Ответов: 453
 Профиль | | #2 Добавлено: 22.08.06 11:19
Проблема в том, что при конвертации в Double изменяется точность представления числа, а мне это совсем не нужно. Пример:

#Compile Exe
#Dim All

#Include "win32api.inc"

Function Test (ByVal p As Double, ByVal p2 As Byte) As Double
 MsgBox Str$(Max (P,P2))
End Function


Function PBMain () As Long
  Test 1.001, 1
End Function

                   

Будет выдан результат: 1.001000004673004 а не 1.001

Ответить

Номер ответа: 3
Автор ответа:
 Dingo



Вопросов: 1
Ответов: 9
 Профиль | | #3 Добавлено: 22.08.06 18:58
В объявлении функций с помощью Declare для параметров можно использовать тип ANY. Т.е. если так вот объявить переменную, то вызывать функцию можно с разными по типу параметрами, в функцию же будет передаваться как раз указатель.
Проблема в том, как уже внутри функции "понять" что передали: например LONG или DOUBLE. Ссылка ссылкой, но данные то разной длины!
Так что здесь видимо придётся (как и предлагается в хелпе) передавать ещё один параметр - для определения типа данных. А это уже не столь эффективно/эффектно.
(И если, не путаю, ANY можно пользовать только в Declare, т.ч. ещё надо чтобы и сама функция была "снаружи", в DLL-ке).

Ответить

Номер ответа: 4
Автор ответа:
 JMP



Вопросов: 6
Ответов: 171
 Профиль | | #4 Добавлено: 22.08.06 19:28
ИМХО не корректный пример


#COMPILE EXE
#DIM ALL

FUNCTION PBMAIN () AS LONG
    LOCAL d AS DOUBLE : d=1.001
    LOCAL w AS WORD   : w=1
    ? STR$(MAX(d,w))
END FUNCTION


здесь же сама вункция MAX гонит, какая связь с конвертацией данных ?

а передавать word,dword,double можно так

#COMPILE EXE
#DIM ALL

FUNCTION Test (BYVAL p AS DOUBLE ) AS DOUBLE
   Test=SIN(p)
END FUNCTION

FUNCTION PBMAIN () AS LONG
  LOCAL w  AS WORD    : w=1
  LOCAL d  AS DOUBLE  : d=1.001
  LOCAL dw AS DWORD   : dw=1

  ? STR$(Test(BYVAL (w))  ;)  : ? STR$(SIN(w)) ' <- проверка
  ? STR$(Test(BYVAL (d))  ;)  : ? STR$(SIN(d))
  ? STR$(Test(BYVAL (dw))  ;) : ? STR$(SIN(dw))
END FUNCTION  

Ответить

Номер ответа: 5
Автор ответа:
 JMP



Вопросов: 6
Ответов: 171
 Профиль | | #5 Добавлено: 22.08.06 20:40
Кстати гонит не MAX а STR$ и FORMAT$

#COMPILE EXE
#DIM ALL

FUNCTION PBMAIN () AS LONG
    LOCAL dbl AS DOUBLE
    LOCAL ex  AS EXT
    dbl =1.001
    ex  =1.001
    ? FORMAT$(dbl,18)
    ? FORMAT$(ex,18)
END FUNCTION

Ответить

Номер ответа: 6
Автор ответа:
 JMP



Вопросов: 6
Ответов: 171
 Профиль | | #6 Добавлено: 22.08.06 20:46
(И если, не путаю, ANY можно пользовать только в Declare, т.ч. ещё надо чтобы и сама функция была "снаружи", в DLL-ке).


Не обязательно, можно итак использовать ANY, но
тип данных конечно надо сообщать


#COMPILE EXE
#DIM ALL

%word=2
%dword=4
%double=8
%ext=10
'****************************************************************
DECLARE FUNCTION fake (BYVAL p AS ANY,BYVAL t AS LONG ) AS DOUBLE
'****************************************************************
FUNCTION Test (BYVAL p AS DWORD, BYVAL t AS LONG) AS DOUBLE
 LOCAL lpW AS WORD PTR
 LOCAL lpDW AS DWORD PTR
 LOCAL lpDBL AS DOUBLE PTR
 LOCAL lpEXT AS EXT PTR
 SELECT CASE t
     CASE %word
        lpW = p : FUNCTION = @lpW
     CASE %dword
        lpDW =p : FUNCTION = @lpDW
     CASE %double
        lpDBL=p : FUNCTION = @lpDBL
     CASE %ext
        lpEXT=p : FUNCTION = @lpEXT
 END SELECT
END FUNCTION
'*****************************************
FUNCTION PBMAIN () AS LONG
 LOCAL w AS WORD            :w =1
 LOCAL dw, func AS DWORD    :dw=1
 LOCAL dbl,dblRes AS DOUBLE :dbl=1.001
 LOCAL ex,extRes AS EXT     :ex =1.0001
 func=CODEPTR(Test)
 CALL DWORD func USING fake(BYVAL VARPTR(w)  ,%word)   TO dblRes  :  ? FORMAT$(dblRes,18)
 CALL DWORD func USING fake(BYVAL VARPTR(dw) ,%dword)  TO dblRes  :  ? FORMAT$(dblRes,18)
 CALL DWORD func USING fake(BYVAL VARPTR(dbl),%double) TO dblRes  :  ? FORMAT$(dblRes,18)
 CALL DWORD func USING fake(BYVAL VARPTR(ex) ,%ext)    TO extRes  :  ? FORMAT$(extRes,18)
END FUNCTION                      

Ответить

Номер ответа: 7
Автор ответа:
 JMP



Вопросов: 6
Ответов: 171
 Профиль | | #7 Добавлено: 22.08.06 23:04
Кстати гонит не MAX а STR$ и FORMAT$


Sorry to PB, ничего там не гонит

#COMPILE EXE
#DIM ALL

FUNCTION PBMAIN () AS LONG
  LOCAL sTemp AS STRING
  LOCAL s  AS SINGLE   : s=1.0000001
  LOCAL d  AS DOUBLE   : d=1.000000000000001
  LOCAL e  AS EXTENDED : e=1.00000000000000001
  sTemp=      "Single      ="+FORMAT$(s,18)+$CRLF
  sTemp=sTemp+"Double    ="+FORMAT$(d,18)+$CRLF
  sTemp=sTemp+"Extended="+FORMAT$(e,18)
  ? sTemp,64,"Report"
END FUNCTION  

просто STR$ и FORMAT$ перед тем как отображать что либо
конвертирует данные в EXTENDED, отсюда и чудеса из мусора
округления, т.е. если сам тип данных не поддерживает такой точности, то в принципе до барабана, что появляеться мусор после конвертации. В случае
если мы назначаем в EXTENDED 0.0001 то сами же игнорируем точность после 1, т.е. нужна точность
значит и назначать надо соответственно до нужного знака =0.00001000000000001

Ответить

Номер ответа: 8
Автор ответа:
 CyRax



Разработчик Offline Client

ICQ: 204447456 

Вопросов: 180
Ответов: 4229
 Web-сайт: basicproduction.nm.ru
 Профиль | | #8
Добавлено: 23.08.06 21:52
Variant использовать не хочется, т.к. считается, что он слишком тормозной.

Скорее массивный, 16 байт всё таки: 8 байт флаг и 8 байт объединение. Оставь 8-байтовое объединение, а флаг можно вообще вынести за процедуру.
Не скажу что это что-то оригинальное, но микрософт то именно так поступает.
#Compile Exe

#Include "WIN32API.INC"

Global FlgType As Byte

Union WDF
 Wrd As Word
 ;Dwd As Dword
 Flt As Double
End Union

Sub Show_WDF(Number As WDF)
 Select Case FlgType
 Case 0
     MsgBox Str$(Number.Wrd),,"Wrd"
 Case 1
     MsgBox Str$(Number.Dwd),,";Dwd"
 Case 2
     MsgBox Str$(Number.Flt),,"Flt"
 End Select
End Sub

Function PBMain
 Dim SendMe As WDF
 SendMe.Wrd=65535
 Show_WDF SendMe

 FlgType=1
 SendMe.Dwd=&HFFFFFFFF
 Show_WDF SendMe

 FlgType=2
 SendMe.Flt=1.25
 Show_WDF SendMe

 FlgType=0
End Function

Ответить

Страница: 1 |

Поиск по форуму



© Copyright 2002-2011 VBNet.RU | Пишите нам