Mathematical Symbols in Python
I often use mathematical symbols in Python code which results in me scrabbling around to find the ones I need so I decided to write a simple module to simplify the process, which I will describe in this article.
Overview
The Unicode character encoding system currently (version 15.0, released September 2022) consists of 149,186 characters in 30 sub-categories. The characters likely to be used for mathematical notation are scattered across several categories so for my mathsymbols
module I gathered them together into a dictionary, and also provided functions for searching the dictionary and printing out details of each symbol.
With nearly 150,000 Unicode characters it is almost inevitable that I have missed some which could be considered mathematical so if you know of any that you think should be included please let me know.
Once you import the mathsymbols
module there are no less than four ways to use them in code which we’ll see later.
The Project
This project consists of the following files:
- mathsymbols.py
- mathsymbolsdemo.py
The source code lives in a Github repository.
The Code
This is the mathsymbols.py file.
from types import MappingProxyType
symbols = MappingProxyType(
{
"set_empty": "∅",
"set_union": "∪",
"set_intersection": "∩",
"set_is_element_of": "∈",
"set_is_not_element_of": "∉",
"set_is_subset_of": "⊆",
"set_is_proper_subset_of": "⊂",
"set_is_not_subset_of": "⊄",
"set_is_superset_of": "⊇",
"set_is_proper_superset_of": "⊃",
"set_is_not_superset_of": "⊅",
"set_universal": "ξ",
"set_minus": "∖",
"set_cartesian_product": "×",
"set_difference": "\\",
"set_symmetric_difference": "Δ",
"set_cardinality": "|",
"set_complement": "'",
"set_power_set": "ℙ",
"set_contains_as_member": "∋",
"set_does_not_contain_as_member": "∌",
"complex_numbers": "ℂ",
"real_numbers": "ℝ",
"rational_numbers": "ℚ",
"integers": "ℤ",
"natural_numbers": "ℕ",
"superscript_i": "ⁱ",
"superscript_n": "ⁿ",
"superscript_plus_sign": "⁺",
"superscript_minus": "⁻",
"superscript_zero_0": "⁰",
"superscript_one_1": "¹",
"superscript_two_2": "²",
"superscript_three_3": "³",
"superscript_four_4": "⁴",
"superscript_five_5": "⁵",
"superscript_six_6": "⁶",
"superscript_seven_7": "⁷",
"superscript_eight_8": "⁸",
"superscript_nine_9": "⁹",
"subscript_zero_0": "₀",
"subscript_one_1": "₁",
"subscript_two_2": "₂",
"subscript_three_3": "₃",
"subscript_four_4": "₄",
"subscript_five_5": "₅",
"subscript_six_6": "₆",
"subscript_seven_7": "₇",
"subscript_eight_8": "₈",
"subscript_nine_9": "₉",
"fraction_one_half_1_2": "½",
"fraction_zero_thirds_0_3": "↉",
"fraction_one_third_1_3": "⅓",
"fraction_two_thirds_2_3": "⅔",
"fraction_one_quarter_1_4": "¼",
"fraction_three_quarters_3_4": "¾",
"fraction_one_fifth_1_5": "⅕",
"fraction_two_fifths_2_5": "⅖",
"fraction_three_fifths_3_5": "⅗",
"fraction_four_fifths_4_5": "⅘",
"fraction_one_sixth_1_6": "⅙",
"fraction_five_sixths_5_6": "⅚",
"fraction_one_seventh_1_7": "⅐",
"fraction_one_eighth_1_8": "⅛",
"fraction_three_eighths_3_8": "⅜",
"fraction_five_eighths_5_8": "⅝",
"fraction_seven_eighths_7_8": "⅞",
"fraction_one_ninth_1_9": "⅑",
"fraction_one_tenth_1_10": "⅒",
"degree_angle": "°",
"degree_celsius": "℃",
"degree_fahrenheit": "℉",
"diameter": "⌀",
"multiplication": "✕",
"division": "÷",
"left_floor": "⌊",
"right_floor": "⌋",
"left_ceiling": "⌈",
"right_ceiling": "⌉",
"product": "∏",
"coproduct": "∐",
"summation": "∑",
"summation_top": "⎲",
"summation_bottom": "⎳",
"partial_differential": "∂",
"integral": "∫",
"top_half_integral": "⌠",
"bottom_half_integral": "⌡",
"not_sign": "¬",
"plus_minus_sign": "±",
"square_root": "√",
"cube_root": "∛",
"fourth_root": "∜",
"proportional_to": "∝",
"infinity": "∞",
"right_angle": "∟",
"angle": "∠",
"therefore": "∴",
"approximately_equal_to": "≅",
"not_equal_to": "≠",
"less_than_or_equal_to": "≤",
"greater_than_or_equal_to": "≥",
"right_angle_with_arc": "⊾",
"right_triangle": "⊿",
"dot_operator": "⋅",
}
)
def search(namelike):
"""
Return a dictionary of symbols with names
containing namelike argument
"""
filtered = {k: v for k, v in symbols.items() if namelike in k}
return filtered
def print_symbols(symbols_to_print = symbols):
"""
Prints symbols in the symbols argument,
or all if this is omitted
"""
for symbol in symbols_to_print.keys():
print(f"{symbol.ljust(32, ' ')}", end="")
print(f" {symbols_to_print[symbol]}", end="")
print(f" decimal: {str(ord(symbols_to_print[symbol])).ljust(5, ' ')}", end="")
print(f" hexadecimal: \\u{hex(ord(symbols_to_print[symbol]))[2:]}")
All my previous articles on Medium have used Github Gists for source code. Medium recently added the ability to post formatted code natively and this is the first time I have used this feature. I hope you like it. If you write articles on Medium which include code you might want to try it yourself. This article by Alex Benzer takes you through the process.
The symbols Dictionary
This dictionary, which is wrapped in a MappingProxyType
to make it immutable, uses brief descriptions as its keys and the characters themselves as values. Note that the descriptions are not the same as those used by Unicode but chosen to be more consistent and easily searchable. This means there is a certain amount of duplication in some keys, for example fractions contain the numbers in both words and digits, eg. fraction_seven_eighths_7_8
.
The search Function
This is a simple list comprehension wrapped as a dictionary, returning any keys/values with a key containing namelike. I didn’t consider it necessary to provide any wildcard options due to the small number of items in the symbols dictionary.
The print_symbols Function
This prints the supplied dictionary, symbols_to_print
, or the entire symbols dictionary if this is not supplied. We can use this function to print a dictionary obtained from the search function.
Now let’s try it out with the mathsymbolsdemo.py program.
import mathsymbols as ms
def main():
print("------------------------")
print("| codedrome.com |")
print("| Mathematical Symbols |")
print("------------------------\n")
ms.print_symbols()
# f = ms.search("root")
# ms.print_symbols(f)
# print using dictionary key
# print(f"12{ms.symbols['superscript_two_2']} = {12**2}")
# print using symbols copied/pasted into code
# print(f"⅝ + ⅛ = ¾")
# print using decimal Unicode
# temp_celsius = 18.5
# print(f"The temperature is {temp_celsius}{chr(8451)}")
# print using hexadecimal Unicode
# print("\u221e + \u221e = \u221e")
if __name__ == "__main__":
main()
This short program demonstrates printing all symbols, searching and printing the result, and the four ways of using symbols in code.
The line currently uncommented calls print_symbols()
without an argument so prints all of the symbols
dictionary. Note that I aliased mathsymbols
as ms
in the import. Run the code thus:
python3 mathsymbolsdemo.py
This will give you the following output. This is truncated to the first 12 lines but you might like to print all 106 symbols and browse through them to see the sort of stuff available. As you can see we also get the Unicode values in decimal and hexadecimal.
Few if any fonts offer a full complement of Unicode characters so there is a chance you might not see some of the more obscure ones. For me the characters in the symbols
dictionary all work fine in VSCode and Firefox, but on my phone (Chrome on Android) they all work except superscript 4. Very strange.
Uncomment the next two lines which search for any symbols containing “root” and print the result. Running the program again gives us this output.
Uncomment the rest of the code (don’t uncomment the actual comments!) which show symbols printed using the following four methods:
- Accessing the dictionary value using the key
- Copying/pasting symbols from the result of using the search function
- Using the decimal code and the chr function
- Using the hexadecimal code prefixed with \u
I can’t see any reason to use either decimal or hexadecimal in Python, but would suggest the ideal usage would be to copy/paste any well known symbols into code, and use the dictionary key for more obscure ones. The latter option makes code self-documenting although admittedly rather long. Ultimately it’s a personal choice based on who is likely to read or maintain your code.
After you have uncommented the last lines of code run the program one more time.
A quick note about using these symbols in HTML. As this is a Python project I have output the hexadecimal values with \u as required in Python code. However, if you need to use them in HTML you can use decimal or hexadecimal codes like this:
&#[decimal];
&#x[hexadecimal];
As I mentioned above, if you know of any Unicode characters of a generally mathematical nature which I have missed please let me know.
This article was previously published on CodeDrome