# Exponentiation (n-ary)

**URL:** <https://racket.discourse.group/t/exponentiation-n-ary/3611>\
**Category:** Show & Tell\
**Created:** [March 8, 2025, 9:41pm UTC](https://racket.discourse.group/t/exponentiation-n-ary/3611 "2025-03-08T21:41:58Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![damien\_mattei](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/damien_mattei/32/2706_2.png) [@damien\_mattei](https://racket.discourse.group/u/damien_mattei)\
**Post date:** [March 8, 2025, 9:41pm UTC](https://racket.discourse.group/t/exponentiation-n-ary/3611/1 "2025-03-08T21:41:58Z")

</div>

Hi,

for this end of week i present an n-ary version of the classic `expt` of Scheme.

I needed it because i use n-ary procedures in infix and it worked with +,-,\*,/ which are n-ary but not with `expt`.

I did not know why Scheme does not provide n-ary exponentiation, perheaps because of the mathematical properties of exponentiation required to made the computation, here are the properties from wikipedia :

 ![exponentiation](https://global.discourse-cdn.com/free1/uploads/racket/original/2X/0/03070da37ce08e5205c9c5bb5b256a88cafce02c.png)

This is translate in Scheme by: `(expt b (expt p q))` because of the right-associativity (conventional).

Example in Python: `b **p** q` , there should exist such a function in scheme : `(** b p q)` but not.

Here is a possible implementation:

```scheme
(define (**-not-tail-rec b . pQ)
    (cond ((null? pQ) 1) ; by convention 2^() = 2⁰ = 1 it is like this in Mathematics
	  ((null? (cdr pQ)) (expt b (car pQ))) ; example : 2³ 
	  (else
	   (expt b (apply **-not-tail-rec pQ))))) ; example 2 ³ ⁴ = 2^(3^4) still like this in Mathematics

```

The above version is working but i prefer a tail recursive version (even if there happen ,with exponentiation ,more quickly an **arithmetic overflow** before a possible **stack overflow** ) :

```scheme
 ;; a tail recursive version with an accumulator
  (define (** b . pQ)
    (define (**-tail-rec p Q)
      (if (null? p)
	    Q ; when finish we return the accumulator
	    (**-tail-rec (cdr p) 
                     (expt (car p) Q)))) ; p ^ Q 

    (if (null? pQ)
	   1 ; by convention 2^() = 2⁰ = 1 it is like this in Mathematics
	   (let ((Qp (reverse pQ))) ; because exponentiation is right-associative we will compute from right to left, so we need to reverse the list
	      (expt b (**-tail-rec (cdr Qp) (car Qp)))))) ; start with Q,a number in the accumulator and p being a list

```

```scheme
(** 2 3 4)
2417851639229258349412352

(** 1.3 2.32 1.876 1.75 1.89)
4.686534791042776e+19

```

checking with Python:

```scheme
Python 3.12.3 (main, Feb 4 2025, 14:48:35) [GCC 13.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> 2 **3** 4
2417851639229258349412352
>>> 1.3 **2.32** 1.876 **1.75** 1.89
4.686534791042776e+19

```

And this will be useful too for the next release of my infix parser for scheme:

```scheme
#lang reader SRFI-105
(require Scheme+/exponentiation)
{1.3 **2.32** 1.876 **1.75** 1.89}
4.686534791042776e+19

```

Damien

---

<div class="post-metadata">

**Author:** ![hendrikboom3](https://avatars.discourse-cdn.com/v4/letter/h/b5e925/32.png) [@hendrikboom3](https://racket.discourse.group/u/hendrikboom3)\
**Post date:** [March 9, 2025, 1:41am UTC](https://racket.discourse.group/t/exponentiation-n-ary/3611/2 "2025-03-09T01:41:43Z")

</div>

Extended infix notation like this is usually reserved in mathematics  
for associative operations.

Exponentiation is not associative.

(3 \*\*3 ) \*\* 3 is different from 3 \*\* (3 \*\* 3)

-- hendrik

---

<div class="post-metadata">

**Author:** ![damien\_mattei](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/damien_mattei/32/2706_2.png) [@damien\_mattei](https://racket.discourse.group/u/damien_mattei)\
**Post date:** [March 9, 2025, 5:43pm UTC](https://racket.discourse.group/t/exponentiation-n-ary/3611/3 "2025-03-09T17:43:15Z")

</div>

yes i had mentioned in my original post the part of wikipedia about that.

But i should be very carefull coding the parser , you can understand what i mean when reading this post about Intel Fortran, a professional compiler:

> **[Fortran Power Operator (\*\*) Precedence Error](https://community.intel.com/t5/Intel-Fortran-Compiler/Fortran-Power-Operator-Precedence-Error/td-p/1155315)**
>
> I am filing a potential bug about the Intel Fortran Compiler. When a negative value is used as a power, the power operation precedence might be wrong. For example, I tested the following code on a Windows 10 x64 machine with Intel(R) Visual Fortran...

this could lead to wrong result when used without parenthesis.

i have to fix (if possible ,because i'm in a melting of infix and prefix! ) such a thing in my own parser before releasing it.

(I think it is possible to fix that without too much complexity)

A lot of language prefer to use exponentiation as a function ( pow in C for example) instead of an operator because it can be confusing due to the special operator precdence rules caused by right-associativity of exponentiation (or non associativity , in mathematic ,instead of computer science there is no such notion of right/left associativity , they simply say it is not associative, and you're right as a mathematician to specify it)

thank you for your remark.

Need to fix now the same problem as about the Intel Fortran compiler now! .....

Regards,

---

<div class="post-metadata">

**Author:** ![damien\_mattei](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/damien_mattei/32/2706_2.png) [@damien\_mattei](https://racket.discourse.group/u/damien_mattei)\
**Post date:** [March 16, 2025, 12:53am UTC](https://racket.discourse.group/t/exponentiation-n-ary/3611/4 "2025-03-16T00:53:14Z")

</div>

Just a few cool feature i'm adding and testing in Scheme+/curly-infix (but not yet commited) :

```scheme
#lang reader SRFI-105
(require Scheme+)

```

```scheme
(define (foo x y) {-4 · sin(x) + x · y ² - 5 · x / y})
(foo 1.23 3.4)
8.640021262861444

```

this is equivalent to python code as :

```scheme
from math import *
def foo(x,y):
     return -4 * sin(x) + x * y ** 2 - 5 * x / y

foo(1.23,3.4)
8.640021262861444

```

some other test examples:

```scheme
{2 ³}
8

```

```scheme
{(2 ³) ⁴}
4096

```

```scheme
{3 · (2 ³ - 1)}
21

```

use the mathematic `·` character for multiplication : AltGr + Maj (CAPS) + 1 --\> · on french keyboard ,Option + h on MacOS (did not know on US keyboard?)

```scheme
{3 ² + 2 · 3 · 5 + 5 ²}
64

```

```scheme
{3 · 5 + 2 ³}
23

```

```scheme
{3 ⁻²}
1/9

```

```scheme
{1 + 3 * - 2 **4** 2 < 0}
#t

```

```scheme
{2 ¹⁰}
1024

```

```scheme
{2 ³ ⁴} ; strange syntax :-) for 2 **3** 4 = 2 **(3** 4)
2417851639229258349412352

```

and more example that all have been tested to give the same result as Python.

note that superscript character are not hard to get on my keyboard (french) in Emacs or Vim, one can use this:

```scheme
;; note: under Linux and on a PC (french) keyboard superscript characters
;; can be generated with the keystroke sequence: ^ n where n is a number or sign
;; under MacOS the keystroke sequence is : Command Shift + n (you really need to type + key for superscript)

;; Using the text editor vim, one can produce subscripted and superscripted numbers by using the digraphs control-k-ns for subscription and control-k-nS for superscription, where n is an Arabic numeral.

```

Good night (in my TimeZone)

---

<div class="post-metadata">

**Author:** ![hendrikboom3](https://avatars.discourse-cdn.com/v4/letter/h/b5e925/32.png) [@hendrikboom3](https://racket.discourse.group/u/hendrikboom3)\
**Post date:** [March 16, 2025, 10:20pm UTC](https://racket.discourse.group/t/exponentiation-n-ary/3611/5 "2025-03-16T22:20:52Z")

</div>

...  
...

> ```scheme
> {2 ³ ⁴} ; strange syntax :-) for 2 **3** 4 = 2 **(3** 4)
> 2417851639229258349412352
> 
> ```

Of course the usual mathematical notation for 2 \*\* (3 \*\* 4) is to have the  
4 be a superscript on the 3, rather as you showed a superscript  
on the 2 \*\* 3. So the 4 needs to be higher and smaller than the 3.

The superscript notation you show us in coventional math notation  
corresponds to (2 \*\* 3) \*\* 4.

-- hendrik

---

<div class="post-metadata">

**Author:** ![damien\_mattei](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/damien_mattei/32/2706_2.png) [@damien\_mattei](https://racket.discourse.group/u/damien_mattei)\
**Post date:** [March 17, 2025, 10:30am UTC](https://racket.discourse.group/t/exponentiation-n-ary/3611/6 "2025-03-17T10:30:38Z")

</div>

> [@hendrikboom3](#):
>
> So the 4 needs to be higher and smaller than the 3.

yes but there is no way in terminal,text editor (Emacs,Vim) to create or display such notation, you can not **superscript** more than one single time.  
And only a few set of character can be superscript for math: the integer numbers positive and negative , also the sign + and - and the parenthesis ( ) .

> **[Superscript Letters - Simple Copy And Paste](https://www.copyandpastesymbols.net/superscript-letter.html)**
>
> Get the best collection of superscript letters with Dec Code, Hex Code, & Unicode. ˢʸᵐᵇᵒˡ Just one click to copy the superscript letters and paste them anywhere.

> **[Unicode subscripts and superscripts](https://en.wikipedia.org/wiki/Unicode_subscripts_and_superscripts)**
>
> Unicode has subscripted and superscripted versions of a number of characters including a full set of Arabic numerals. These characters allow any polynomial, chemical and certain other equations to be represented in plain text without using any form of markup like HTML or TeX.
> The World Wide Web Consortium and the Unicode Consortium have made recommendations on the choice between using markup and using superscript and subscript characters:
> When used in mathematical context (MathML) it is rec...

Example (from the source code Scheme+/superscript):

```scheme
(define script-string "⁻⁺⁰¹²³⁴⁵⁶⁷⁸⁹") ; super script

```

(BTW: i could add support for symbols and a few arithmetic with ( ) also)

To be used this should accessible by the keyboard in many geographic versions, example is 'lambda' symbol λ which is not often used because not easy to get on keyboard. (unless on Mac OS where does exist a shortcut Control + Command + Space)

I added the notation below **lately** to allow multiple level of exponentiation , but perheaps i should remove this feature, the original idea was to allow "natural" math notation in Scheme+ but this now goes the opposite as it is ambiguous and can lead to errors of understanding the code.

> [@hendrikboom3](#):
>
> ```scheme
> {2 ³ ⁴} ; strange syntax :-) for 2 **3** 4 = 2 **(3** 4)
> 2417851639229258349412352
> 
> ```

I had the 2 versions with one commented in code of parser:

```scheme
(def (sexpr-superscript lst) ; deal with **
  (when (null? lst)
    (return lst))
  (define elem (car lst))
  (cond ((operator-symbol-or-syntax? elem) (cons elem ; we keep it in the resulting list
						 (superscript-operator-loop (cdr lst)))) ; and loop in the superscript-operator-loop state
	((superscript? elem) (cons '**;'expt ;(syntax**) ;' **;** with superscript
				   (cons (syntax-superscript-number->number elem) ; number
					 ;;(superscript-operator-loop (cdr lst))))) ; forbid repeated superscript
					(sexpr-superscript (cdr lst))))) ; loop (follow automata) 
	(else ; got an other sexpr, we keep it in the resulting list
	       (cons elem
		     (sexpr-superscript (cdr lst)))))) ; loop in the same state

```

so it is really easy to change it, i do not know what i will do in the release of code, i think i can leave it as an **hidden feature** but perheaps i will remove it definitively.

The finite state machine for this part of parser is quite simple, it just replace any superscript encountered by `**` followed by the superscript number translated in normal number:

 ![parser-superscript](https://global.discourse-cdn.com/free1/uploads/racket/original/2X/2/2546d4273ab5ad9d4ed719e1efa5aabb3c1c3d42.png)

Here is a debug ouput of a single example:

```scheme
Welcome to DrRacket, version 8.15 [cs].
Language: reader SRFI-105, with debugging; memory limit: 14000 MB.
SRFI-105 Curly Infix parser for Racket Scheme and R6RS by Damien MATTEI
(based on code from David A. Wheeler and Alan Manuel K. Gloria.)

Possibly skipping some header's lines containing space,tabs,new line,etc or comments.

SRFI-105.rkt : number of skipped lines (comments, spaces, directives,...) at header's beginning : 12

Parsed curly infix code result = 

(module repl racket (provide (all-defined-out)) (require Scheme+))
> {2 ³}

($nfx$ 2 ³)
!*prec-generic-infix-parser : terms=(.#<syntax 2> .#<syntax ³>)
!*prec-generic-infix-parser : parsed-superscript=(.#<syntax 2> ** 3)
!*prec-generic-infix-parser : parsed+-=(.#<syntax 2> ** 3)
!*prec-generic-infix-parser : deep-terms=(.#<syntax 2> ** 3)
!*prec-generic-infix-parser 1 : deep-terms=(.#<syntax 2> ** 3)
!*prec-generic-infix-parser : recalling recall-infix-parser via map
recall-infix-parser : expr =.#<syntax 2>
recall-infix-parser : detected syntax,passing from syntax to list (will be used if it is a list)
recall-infix-parser (after syntax test) : expr= .#<syntax 2>
recall-infix-parser : (list? expr)= #f
recall-infix-parser : expr not list.
recall-infix-parser : expr =**
recall-infix-parser (after syntax test) : expr= **
recall-infix-parser : (list? expr)= #f
recall-infix-parser : expr not list.
recall-infix-parser : expr =3
recall-infix-parser (after syntax test) : expr= 3
recall-infix-parser : (list? expr)= #f
recall-infix-parser : expr not list.
!*prec-generic-infix-parser 2 : deep-terms=(.#<syntax 2> ** 3)
!*prec-generic-infix-parser : rv : deep-terms:(.#<syntax 2> ** 3)
$nfx$ op1 e1 : parsed-args=.#<syntax (** 2 3)>
8

#<eof>

```

and the whole code of module is :

```scheme
(module superscript-parser racket/base

	(provide superscript-operator-loop)

	(require Scheme+/superscript
		 Scheme+/def
		 Scheme+/operators)

	;; parsing superscript ⁻⁺⁰¹²³⁴⁵⁶⁷⁸⁹ natural numbers
	;; see parser-superscript.odg or jpeg image file

;; note: under Linux and on a PC (french) keyboard superscript characters
;; can be generated with the keystroke sequence: ^ n where n is a number or sign
;; under MacOS the keystroke sequence is : Command Shift + n (you really need to type + key for superscript)

;; Using the text editor vim, one can produce subscripted and superscripted numbers by using the digraphs control-k-ns for subscription and control-k-nS for superscription, where n is an Arabic numeral.

	
;; {3 · 5 + 2}
;; 17

;; {3 · 5 + 2 ³}
;; !*-generic-infix-parser : terms = ((.#<syntax +> (.#<syntax ·> .#<syntax 3> .#<syntax 5>) (**.#<syntax 2> 3)))
;; $nfx$ : parsed-args=.#<syntax (+ (· 3 5) (** 2 3))>
;; 23

;; {3 ² + 2 · 3 · 5 + 5 ²}
;; 64

;; {3 ⁻²}
;; 1/9

;; {2 ¹⁰}
;; 1024

(define (error-superscript lst)
  (error "Error parsing superscript : the superscript are in a wrong position in the list: " lst))

(def (superscript-operator-loop lst)
  ;;(display "superscript-operator-loop : lst=") (display lst) (newline)
  (when (null? lst)
    (return lst))
  (define elem (car lst))
  (cond ((operator-symbol-or-syntax? elem) (cons elem ; we keep it in the resulting list
						 (superscript-operator-loop (cdr lst)))) ; and loop in the same machine state
	((superscript? elem) (error-superscript lst))
	(else
	 (cons elem ; we keep it in the resulting list
	       (sexpr-superscript (cdr lst))))))

(def (sexpr-superscript lst) ; deal with **
  (when (null? lst)
    (return lst))
  (define elem (car lst))
  (cond ((operator-symbol-or-syntax? elem) (cons elem ; we keep it in the resulting list
						 (superscript-operator-loop (cdr lst)))) ; and loop in the superscript-operator-loop state
	((superscript? elem) (cons '**;'expt ;(syntax**) ;' **;** with superscript
				   (cons (syntax-superscript-number->number elem) ; number
					 ;;(superscript-operator-loop (cdr lst))))) ; forbid repeated superscript
					(sexpr-superscript (cdr lst))))) ; loop (follow automata) 
	(else ; got an other sexpr, we keep it in the resulting list
	       (cons elem
		     (sexpr-superscript (cdr lst)))))) ; loop in the same state

) ; end module

;; {2 ⁴ ²}
;; 65536

;; {- 2 ³}
;; -8

;; {3 * - 2 ⁴ ² + 1}
;; -196607

```
