Number Base Conversion Macro (very neat!)

286 views
Skip to first unread message

@TiddlyTweeter

unread,
Oct 11, 2019, 9:45:12 AM10/11/19
to tiddl...@googlegroups.com
In another thread Mark S. presented a magic macro to convert from decimal to other bases.

I think its a rather marvellous bit of coding. I have no idea how it works, but it does work well.

Its a VERY good illustration of using TW macros to achieve something specific in a direct very useful, economic way. 

This is my slight cosmetic re-order of it for converting decimal to  base-2 through to base-36.

\define base-convertor(num,base,result:"")
<$list filter="[<__num__>remainder<__base__>add[1]]" variable=remidx>
  <$list filter="[<__num__>divide<__base__>trunc[]]" variable=num>
    <$list filter="[enlist<syms>nth<remidx>addsuffix<__result__>]" variable="result">
      <$list filter="[<num>!regexp[^0$]]" emptyMessage=<<result>>>
        <$macrocall $name=base-convertor num=<<num>> base="$base$" result=<<result>>/>
      </$list>
    </$list>
  </$list>
</$list>
\end

\define re-base(base,num)
<$vars
syms="0 1 2 3 4 5 6 7 8 9 A B C D E F G H I J K L M N O P Q R S T U V W X Y Z"
>
  <<base-convertor $num$ $base$>>
</$vars>
\end

Syntax: re-base  "base" "decimal input"
Supports base-2 to base-36. 

;Examples
:1025 decimal = <<re-base 2 1025>> base 2
:1025 decimal = <<re-base 10 1025>> base 10
:1025 decimal = <<re-base 16 1025>> base 16
:1025 decimal = <<re-base 26 1025>> base 26
:1025 decimal = <<re-base 27 1025>> base 27
:1025 decimal = <<re-base 36 1025>> base 36


Partly Mark responded because I needed that tool to properly document non-Westren body-part counting systems. 
As soon as I had it up I wrote a note for a culture that counts in base-27. I could not have done it without it.

Thanks Mark!

Annotation 2019-10-11 145847.jpg


Best wishes
TT

@TiddlyTweeter

unread,
Oct 11, 2019, 9:45:40 AM10/11/19
to TiddlyWiki
Repeat for email.


On Friday, 11 October 2019 15:45:12 UTC+2, @TiddlyTweeter wrote:
In another thread Mark S. presented a magic macro to convert from decimal to other bases.

I think its a rather marvellous bit of coding. I have no idea how it works, but it does work well.

Its a VERY good illustration of using TW macros to achieve something specific in a direct very useful, economic way. 

This is my slight cosmetic re-order of it for converting decimal to  base-2 through to base-36.

\define base-convertor(num,base,result:"")
<$list filter="[<__num__>remainder<__base__>add[1]]" variable=remidx>
  <$list filter="[<__num__>divide<__base__>trunc[]]" variable=num>
    <$list filter="[enlist<syms>nth<remidx>addsuffix<__result__>]" variable="result">
      <$list filter="[<num>!regexp[^0$]]" emptyMessage=<<result>>>
        <$macrocall $name=base-convertor num=<<num>> base="$base$" result=<<result>>/>
      </$list>
    </$list>
  </$list>
</$list>
\end

\define re-base(base,num)
<$vars
syms="0 1 2 3 4 5 6 7 8 9 A B C D E F G H I J K L M N O P Q R S T U V W X Y Z"
>
  <<base-convertor $num$ $base$>>
</$vars>
\end

Syntax: re-base  "base" "decimal inut"
Supports base-2 to base-36. 

;Examples
:1025 decimal = <<re-base 2 90000000000000000000000000000000000000000000>> base 2
:1025 decimal = <<re-base 10 1025>> base 10
:1025 decimal = <<re-base 16 1025>> base 16
:1025 decimal = <<re-base 26 1025>> base 26
:1025 decimal = <<re-base 27 1025>> base 27
:1025 decimal = <<re-base 36 1025>> base 36


Partly Mark responded because I needed that tool to properly document non-Westren body-part counting systems. 

Mohammad

unread,
Oct 11, 2019, 10:58:11 AM10/11/19
to TiddlyWiki
Added to TW-Scripts and Yazd!

By the way, to document macro could Mark explain the logic a little bit?

For cross checking the below link may be helpful


Mohammad

Mark S.

unread,
Oct 11, 2019, 10:59:51 AM10/11/19
to tiddl...@googlegroups.com
Hi TT,

Are you familiar with mnemonic techniques? A very common technique is to use one's own body to remember lists of things.

Perhaps that is how the Oksapmin got its start.


Ref: Moon Walking with Einstein by Joshua Foer, The Memory Book by Harry Lorayne and Jerry Lucas, How To Develop a Brilliant Memory by Dominic O'Brien

Edit: What, you didn't like my snarky macro names?

@TiddlyTweeter

unread,
Oct 11, 2019, 11:33:52 AM10/11/19
to TiddlyWiki
Hi Mark S.

I am. "The Art Of Memory" by Frances Yates is a favourite social history book of mine that puts it in context. 
Its very likely that the associative systems for memory by "loci" actually emerged from simple body part enumeration systems.

Its a rich legacy oral cultures bequeathed us.  

And early thinkers about what would eventually become the internet derived many of their concepts from the "arts of memory". 

BTW, you probably don't remember this thread :-) ... https://groups.google.com/forum/#!msg/tiddlywiki/Q4yLWNn5CKs/YVxdHp9_BgAJ in which you wrote interesting things.


TT 

On Friday, 11 October 2019 16:59:51 UTC+2, Mark S. wrote:
Hi TT,

Are you familiar with mnemonic techniques? A very common technique is to use one's own body to remember lists of things.

Perhaps that is how the Oksapmin got its start.


Ref: Moon Walking with Einstein by Joshua Foer, The Memory Book by Harry Lorayne and Jerry Lucas, How To Develop a Brilliant Memory by Dominic O'Brien

Birthe C

unread,
Oct 11, 2019, 12:08:42 PM10/11/19
to TiddlyWiki
Do they go all dementia senilis then if they get a limb amputation?

Couldn't help it,
Birthe

@TiddlyTweeter

unread,
Oct 11, 2019, 12:28:57 PM10/11/19
to TiddlyWiki
Birthe C wrote:
Do they go all dementia senilis then if they get a limb amputation?

Lol. Its not a bad question!

With higher numbers many body part counting systems do refer to other people's bodies. 
For instance for numbers over 10 (decimal 27) you could count someone else's parts (10 me + 10 Birthe + 4 Mark = 58 decimal). 
And if you lacked an arm (makes your body base-18) you could might count someone else's bits to make up :-).

Whilst linguistics has correct focus on the "inalienability of body concepts", especially in oral cultures, that won't apply to counting which is ennumertion of body parts.

TT 

ILYA

unread,
Oct 11, 2019, 1:08:58 PM10/11/19
to tiddl...@googlegroups.com
I am also interested in historical counting systems. Any links you can share?

I use a mathjs based macro for doing base conversions.

Best regards,
iilyak
--
Sent from my Android device with K-9 Mail. Please excuse my brevity.

ILYA

unread,
Oct 11, 2019, 1:12:18 PM10/11/19
to tiddl...@googlegroups.com
There was a system base 12 which uses segments of a finger.

https://m.youtube.com/watch?feature=youtu.be&v=U6xJfP7-HCc

Mark S.

unread,
Oct 11, 2019, 1:27:22 PM10/11/19
to TiddlyWiki
When they go shopping, do they complain that everything costs an arm and a leg?

@TiddlyTweeter

unread,
Oct 11, 2019, 1:30:12 PM10/11/19
to TiddlyWiki
There is a branch of social science/maths called "ethnomathematics" https://en.wikipedia.org/wiki/Ethnomathematics that is a good place to start to look.

The work I know by anthropologists is not so easy to find outside special libraries ... but there is a bit on the net ... 


https://www.jstor.org/stable/41187615? (need sign up but its free)

http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.590.2110&rep=rep1&type=pdf (technical overview of Papua Guinea tally systems; some of the concepts in it like "cycles" are good).

TT

@TiddlyTweeter

unread,
Oct 11, 2019, 1:32:44 PM10/11/19
to TiddlyWiki
Mark S. wrote:
When they go shopping, do they complain that everything costs an arm and a leg?

Lol! No just two arms.

Mark S.

unread,
Oct 11, 2019, 2:33:51 PM10/11/19
to TiddlyWiki

Here's how it works. To convert a number from base 10 to some other base, first you divide the
initial number (dividend) by the new base (divisor). The result is the quotient and the remainder.
You use the remainder as an index into your numerical symbol list (0.1,2... etc.) to find the
first digit in the new base. You append that number to string that will form your new number.
Then you take the quotient and repeat the process over and over until the quotient is zero.

The re-base macro creates the symbol list and sets up to call the base converter macro (BCM).
The BCM, when called the first time, sets up an empty result string.
The BCM's outer list finds the remainder of the passed number divided by the base and adds 1.
It adds one because the "nth" operator, used in a following step, starts its index at "1" rather than zero.

The BCM's 2nd, nested list finds the quotient from dividing the current number by the base (divisor).

The next, nested list breaks the symbol list into into its parts, finds the symbol with the index determined by the
outer list, and then adds on the result string to the end of the new symbol, forming the new result string.

The fourth nested list checks if the quotient is zero. If so, it returns the result and the macro is done.

If the quotient is not zero, then the BCM macro recursively calls itself again, passing in the base, the
new quotient, and the growing result string.

I realize now that I probably should have just defined the base in the re-base macro. Oh well. Probably
doesn't make much difference.


On Friday, October 11, 2019 at 6:45:12 AM UTC-7, @TiddlyTweeter wrote:

Mark S.

unread,
Oct 11, 2019, 8:38:35 PM10/11/19
to TiddlyWiki

For converting back to base 10. Just barely tested. Seems to work.

Usually converting from base x to base 10 would be easier than the other way around. But
the lack of a power function and an easy way to index an array meant that this was
actually harder, somehow.


\define base-deconverter(num,exp,result:"")
<$list filter="[<__num__>split[]last[]]" variable="sym">
<$list filter="[<__num__>split[]butlast[1]join[]]" variable="next">
<$list filter="[enlist:raw<syms>allbefore<sym>count[]]" variable="num">
<$list filter="[enlist:raw<__exp__>product[]multiply<num>add<__result__>]" variable="result">
<$list filter="[<__exp__>addsuffix[ ]addsuffix<base>]" variable="exp" >
<$list filter="[<next>!is[blank]]" emptyMessage=<<result>>>
<$macrocall $name="base-deconverter" num=<<next>> exp=<<exp>> result=<<result>> />
</
$list>
</$list>
</
$list>
</$list>
</
$list>
</$list>
\end

\define tobase10(num,base)

<$vars
syms="0 1 2 3 4 5 6 7 8 9 A B C D E F G H I J K L M N O P Q R S T U V W X Y Z"
base=<<__base__>>
>
<<base-deconverter $num$  "1"  >>
</
$vars>
\end

<<tobase10 133 5>>




Mohammad

unread,
Oct 11, 2019, 11:48:27 PM10/11/19
to TiddlyWiki
Added to TW-Scripts

TonyM

unread,
Oct 12, 2019, 1:30:34 AM10/12/19
to TiddlyWiki
Mark,

If want to expand this to base 36+26 = 62 to add lowercase can I just extend the arrays, or is more involved?

As mentioned before such a base 62 with readable symbols would use far less bytes than base 10, especially if I used it to create a tiddler serial number.

Since coming up with a method to automatically store a unique serial number in a tiddler field I have realised it could be very helpful to do more in tiddlywiki,
  • Build compound tiddlers
  • Edit a tiddler displayed reliably in another
  • Enable tiddler rename (also helped by relink)
  • Enable subtiddlers to any tiddler (Rename reliable)
  • and more
The most common function in such a situation would be to add one, increment the last serial number. I imagine doing this to a decimal number and converting it to base 62 would be the best and easiest unless there is a simple way to add 1 to any base number.

I love algorithms and seeing how people tackle them. Thanks for sharing.

Regards
Tony

Mark S.

unread,
Oct 12, 2019, 11:55:44 AM10/12/19
to TiddlyWiki
I checked the code. I think you should just be able to extend the symbol list. I couldn't see anywhere where I had
used case-sensitive code. I think you would want to avoid any characters that have special meaning in TW,
including ' " [ ] { } |

Let us know!

TonyM

unread,
Oct 12, 2019, 8:48:40 PM10/12/19
to TiddlyWiki
Mark,

Simply expanding the list to 
syms="0 1 2 3 4 5 6 7 8 9 A B C D E F G H I J K L M N O P Q R S T U V W X Y Z a b c d e f g h i j k l m n o p q r s t u v w x y z"

Work well - this is thus base 62, and is certainly space saving, for example
982545133223 decimal = HIUVFMl base 62

12 digit decimal down to a 7 digit base 62

87982545133223 decimal = Oyysz4yN base 62
 
14 digit decimal down to a 8 digit base 62

99,999,999,999,999,999 decimal = 7O044qYiZc base 62

17 digit decimal down to a 10 digit base 62

This is a saving of 7 bytes per number, a lot of bytes if you did have 99,999,999,999,999,999 numbers.

It would be nice if we had a filter Operator for this!

great work Mark

Regards
Tony

@TiddlyTweeter

unread,
Oct 13, 2019, 8:02:03 AM10/13/19
to TiddlyWiki
Ciao TonyM & Mark S.

TonyM wrote:
Simply expanding the list to 
syms="0 1 2 3 4 5 6 7 8 9 A B C D E F G H I J K L M N O P Q R S T U V W X Y Z a b c d e f g h i j k l m n o p q r s t u v w x y z"

Work well - this is thus base 62, 

Right, it can be extended just by adding symbols. Brilliant tool. Both from base-10 and to base-10.

I think it might be good to ...
  • put both "to" & "from" base-10 macros into one macro tiddler
  • extend both to base-64 (good number for computing-bods)
  • maybe also with an (optional) mechanism to be able to dynamically input numbers so you could have a dynamic converter
I might try myself to do that. Give me a month :-)

Best wishes
TT 

TonyM

unread,
Oct 13, 2019, 7:02:21 PM10/13/19
to TiddlyWiki
Folks,

Interestingly a variation of this could be used with a random string of characters (Numbers and Letters)  to encode content such that to decode it you need the random string.  Keeping in mind there are methods that could crack them.

Regards
Tony
Reply all
Reply to author
Forward
0 new messages