Wish: Sign(n) function

Widget

Well-Known Member
Licensed User
Longtime User
I'd like to see a Sign(n) function that would return:

-1 if n is negative, 0 if n=0, and 1 if n is positive.

If it were a native function, it would be faster than using If Statements. Many programming languages already have a Sign() function.

Widget
 

Widget

Well-Known Member
Licensed User
Longtime User
The performance of a solution with 'if' should be similar to the native function performance.

Erel,
Well I would create my own Sub Sign(d as double) and call that so the code is easier to read. I thought the extra overhead of the sub call and the if statements would be considerably slower than calling the Android SigNum(d) function directly.

Widget
 

DaOel

Member
Licensed User
Longtime User
Signum function

The native function does exist, it's:
Signum(d)
in Android.

Best regards.

i tried it but it doesnt recognize the function "Signum()" . do i need to set a reference to an math-library?
 

joseluis

Active Member
Licensed User
Longtime User
I tried to access signum, and other native math functions via Reflection library, but this code is wrong.
B4X:
r.Target=r.CreateObject("java.lang.Math")
r.Target=r.RunMethod2("signum", number, "java.lang.double")
The thing is that I cannot create a Math Object. So what would be the right way to do it?
 

joseluis

Active Member
Licensed User
Longtime User
Thank you. Although I was hoping to deepen my knowledge of the Reflection lib
 

stevel05

Expert
Licensed User
Longtime User
To assist your reflection knowledge, the signum method is a static method, so you don't need to create the Math object.


Try this:

B4X:
Dim num As Float   
num = -50.0
Dim r As Reflector
result=r.RunStaticMethod("java.lang.Math","signum",Array As Object(num),Array As String("java.lang.float"))
Log(Result)

Steve
 

joseluis

Active Member
Licensed User
Longtime User
It's true, agraham. Below is the code that demonstrates that the function implemented as a sub is around 100-200 times faster than the one that uses Reflection.

B4X:
Dim timestart, signtime, rsigntime As Long
Dim n As Int
   
' Test Sign function using Reflection
timestart = DateTime.Now
For n = 0 To 100000
   RSign(-20)
Next
rsigntime = DateTime.Now - timestart
   
' Test Sign function using Sub
timestart = DateTime.Now
For n = 0 To 100000
   Sign(-20)
Next
signtime = DateTime.Now - timestart

' Log the result   
Log("Sign: " & signtime & " RSign:" & rsigntime & " rel:" & Round(rsigntime/signtime))


Sub RSign(num As Float) As Int
   Return r.RunStaticMethod("java.lang.Math", "signum", _
      Array As Object(num), Array As String("java.lang.float"))   
End Sub

Sub Sign(d As Double) As Int
    If d = 0 Then
        Return 0
    Else
        Return(d / Abs(d))
    End If
End Sub

HTML:
Sign:27 RSign:4790 rel:177
Sign:27 RSign:5028 rel:186
Sign:22 RSign:2950 rel:134
Sign:19 RSign:2980 rel:157
Sign:33 RSign:3701 rel:112
Sign:21 RSign:2899 rel:138
 

kickaha

Well-Known Member
Licensed User
Longtime User
You can optimise the sign sub:
B4X:
Sub Sign(d As Double) As Int    
If d = 0 Then Return 0
Return(d / Abs(d))
End Sub
Not sure if it would be (much) faster though.
 

myriaddev

Active Member
Licensed User
Longtime User
Faster still is:

Taking out divide, it returns results 1.44 times faster.
 

Attachments

  • faster.txt
    129 bytes · Views: 278

joseluis

Active Member
Licensed User
Longtime User
Yeah, myriadev's version without division is 200-300 times faster than using reflection . Although I must say that calling the slowest one 100000 times takes less than 3 seconds for my SGII.
 
Last edited:

myriaddev

Active Member
Licensed User
Longtime User
Great Joseluis

Hi Joseluis. I can always learn from the masters!
Could you show me your test code including my code ?
Thanks, Jerry
 

joseluis

Active Member
Licensed User
Longtime User
It's pretty strightforward but for sake of completion I attach a functional example.

I can always learn from the masters too. I'm just a newbie. Enjoy
 

Attachments

  • SignExample.zip
    6.1 KB · Views: 260

kickaha

Well-Known Member
Licensed User
Longtime User
Taking out divide, it returns results 1.44 times faster.

So would this be faster (taking out the ELSE)
B4X:
Sub sign(d As Double) As Int
   If d = 0 Then Return 0
   If d > 0 Then Return 1
   Return -1
End Sub
 

joseluis

Active Member
Licensed User
Longtime User
I made an updated version of the Test Suite so now we can easily compare the performance of each one of the sub variations. It runs the test a number of times, showing each partial result. Then it stops and shows the total averaged results.

These are the average results from repeating 10 times a 500000 calls test.

HTML:
R:19186 signND:100 signND:52 signNDNE:54
R/sign:192 R/signND:369 R/signNDNE:355
---
R:13462 signND:100 signND:48 signNDNE:49
R/sign:135 R/signND:280 R/signNDNE:275
---
R:13402 signND:97 signND:48 signNDNE:48
R/sign:138 R/signND:279 R/signNDNE:279
---
R:14145 signND:97 signND:48 signNDNE:49
R/sign:146 R/signND:295 R/signNDNE:289
---
R:13666 signND:99 signND:47 signNDNE:48
R/sign:138 R/signND:291 R/signNDNE:285
---
R:13576 signND:97 signND:49 signNDNE:48
R/sign:140 R/signND:277 R/signNDNE:283
---
R:13561 signND:98 signND:49 signNDNE:48
R/sign:138 R/signND:277 R/signNDNE:283
---
R:13880 signND:119 signND:50 signNDNE:50
R/sign:117 R/signND:278 R/signNDNE:278
---
R:13914 signND:97 signND:48 signNDNE:48
R/sign:143 R/signND:290 R/signNDNE:290
---
R:13584 signND:100 signND:50 signNDNE:49
R/sign:136 R/signND:272 R/signNDNE:277
--------------
R:14237 sign:100 signND:48 signNDNE:49
 R/sign:142 R/signND:297 R/signNDNE:291

R: version using reflection
sign: sub version using division (klaus)
signND: sub version without using division (myriaddev)
signNDNE: sub version without using division nor elses (kickaha)

Two last ones are equally fast. The difference must be only syntactical.
 

Attachments

  • SignExample_v5.zip
    6.4 KB · Views: 229
Cookies are required to use this site. You must accept them to continue using the site. Learn more…