How to do Log2 ?

Just starting out? Need help? Post your questions and find answers here.
TeraByte
User
User
Posts: 40
Joined: Wed May 09, 2012 12:40 am

How to do Log2 ?

Post by TeraByte »

I need the function Log2 and came up with the following:

Code: Select all

Define x.d, num.d
x = 8
num = Log(x)/Log(2)
which gives num = 2.99999999999996 which is close but not exact. The exact answer is 3 which is 2^3 = 8 or Log2(8) = 3. Perhaps this difference is due to floating point error.

QUESTION:
Is there a better way to calculate Log2 than the above?

Thank you.
User avatar
skywalk
Addict
Addict
Posts: 4211
Joined: Wed Dec 23, 2009 10:14 pm
Location: Boston, MA

Re: How to do Log2 ?

Post by skywalk »

You already have the correct answer for a double.

Code: Select all

Define x.d, num.d
x = 8
num = Log(x)/Log(2)
Debug num
x = 3 * 6.1 / 2 / 6.1 * 2
Debug x
x = 3
Debug x
The nice thing about standards is there are so many to choose from. ~ Andrew Tanenbaum
User avatar
Shield
Addict
Addict
Posts: 1021
Joined: Fri Jan 21, 2011 8:25 am
Location: 'stralia!
Contact:

Re: How to do Log2 ?

Post by Shield »

Code: Select all

#Log2 = 0.6931471805599453094

Define x.d
Define num.d

x = 8
num = Log(x) / #Log2

debug num
Image
Blog: Why Does It Suck? (http://whydoesitsuck.com/)
"You can disagree with me as much as you want, but during this talk, by definition, anybody who disagrees is stupid and ugly."
- Linus Torvalds
User avatar
STARGÅTE
Addict
Addict
Posts: 2227
Joined: Thu Jan 10, 2008 1:30 pm
Location: Germany, Glienicke
Contact:

Re: How to do Log2 ?

Post by STARGÅTE »

if you want to use it for quads and use only integers:

Code: Select all

Procedure Log2(Quad.q)
	While Quad <> 0
		Result + 1
		Quad>>1
	Wend
	ProcedureReturn Result-1
EndProcedure

Debug Log2(8)
Debug Log2(1024)
PB 6.01 ― Win 10, 21H2 ― Ryzen 9 3900X, 32 GB ― NVIDIA GeForce RTX 3080 ― Vivaldi 6.0 ― www.unionbytes.de
Lizard - Script language for symbolic calculations and moreTypeface - Sprite-based font include/module
wilbert
PureBasic Expert
PureBasic Expert
Posts: 3942
Joined: Sun Aug 08, 2004 5:21 am
Location: Netherlands

Re: How to do Log2 ?

Post by wilbert »

Code: Select all

Procedure.d Log2(x.d)
  Protected l.d = x
  !fld1
  !fld qword [p.v_l]
  !fyl2x
  !fstp qword [p.v_l]
  ProcedureReturn l
EndProcedure
TeraByte
User
User
Posts: 40
Joined: Wed May 09, 2012 12:40 am

Re: How to do Log2 ?

Post by TeraByte »

Thank you for your excellent replies.
Little John
Addict
Addict
Posts: 4777
Joined: Thu Jun 07, 2007 3:25 pm
Location: Berlin, Germany

Re: How to do Log2 ?

Post by Little John »

2wilbert:
Very cool! 8)

What is the minimal required prozessor for running this code?

Regards, Little John
wilbert
PureBasic Expert
PureBasic Expert
Posts: 3942
Joined: Sun Aug 08, 2004 5:21 am
Location: Netherlands

Re: How to do Log2 ?

Post by wilbert »

Little John, an old 486 processor should be sufficient.
Little John
Addict
Addict
Posts: 4777
Joined: Thu Jun 07, 2007 3:25 pm
Location: Berlin, Germany

Re: How to do Log2 ?

Post by Little John »

Great, thank you!
jack
Addict
Addict
Posts: 1358
Joined: Fri Apr 25, 2003 11:10 pm

Re: How to do Log2 ?

Post by jack »

a little shorter :twisted:

Code: Select all

Procedure.d Log2(x.d)
  !fld1
  !fld qword [p.v_x]
  !fyl2x
  ProcedureReturn
EndProcedure
return value can be left in st(0) :)
wilbert
PureBasic Expert
PureBasic Expert
Posts: 3942
Joined: Sun Aug 08, 2004 5:21 am
Location: Netherlands

Re: How to do Log2 ?

Post by wilbert »

jack wrote:a little shorter
I know it's shorter.
The main reason why I did it a bit different is that I wasn't sure your solution would work on x64 since that officially expects a floating point value to be returned in xmm0.
I figured if I would PureBasic let handle the way it returns the value that that might be a more stable option. But maybe I'm wrong 8)

Another option, if you only need the integer part of the result and the source is a double is to do it like this

Code: Select all

x.d = 64
Debug PeekW(@x + 6) >> 4 - 1023
If both source and result are integer, you can also use bsr

Code: Select all

Procedure.i Log2(x.i)
  CompilerIf #PB_Compiler_Processor = #PB_Processor_x86
    !mov eax, -1
    !bsr edx, [p.v_x]
    !cmovnz eax, edx
  CompilerElse
    !mov rax, -1
    !bsr rdx, [p.v_x]
    !cmovnz rax, rdx
  CompilerEndIf
  ProcedureReturn
EndProcedure
Post Reply