{"id":8133,"date":"2025-12-08T17:03:51","date_gmt":"2025-12-08T11:33:51","guid":{"rendered":"https:\/\/tutorpython.com\/?p=8133"},"modified":"2025-12-08T17:17:31","modified_gmt":"2025-12-08T11:47:31","slug":"zeta-function-in-python","status":"publish","type":"post","link":"https:\/\/tutorpython.com\/zeta-function-in-python","title":{"rendered":"Zeta Function in Python"},"content":{"rendered":"<div id=\"ez-toc-container\" class=\"ez-toc-v2_0_80 counter-hierarchy ez-toc-counter ez-toc-transparent ez-toc-container-direction\">\n<div class=\"ez-toc-title-container\"><p class=\"ez-toc-title\" style=\"cursor:inherit\">In This Article<\/p>\n<\/div><nav><ul class='ez-toc-list ez-toc-list-level-1 ' ><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-1\" href=\"https:\/\/tutorpython.com\/zeta-function-in-python\/#The_Riemann_Zeta_Function_in_Python\" >The Riemann Zeta Function in Python<\/a><ul class='ez-toc-list-level-3' ><li class='ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-2\" href=\"https:\/\/tutorpython.com\/zeta-function-in-python\/#Using_SciPy_to_compute_the_Riemann_Zeta_Function_in_Python\" >Using SciPy to compute the Riemann Zeta Function in Python<\/a><\/li><\/ul><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-3\" href=\"https:\/\/tutorpython.com\/zeta-function-in-python\/#The_Hurwitz_Zeta_Function_in_Python\" >The Hurwitz Zeta Function in Python<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-4\" href=\"https:\/\/tutorpython.com\/zeta-function-in-python\/#Visualizing_the_Zeta_Function_with_Hurwitz_Generalization\" >Visualizing the Zeta Function with Hurwitz Generalization<\/a><\/li><\/ul><\/nav><\/div>\n<p>The <strong>Zeta function<\/strong> encompasses a family of important mathematical functions, primarily including the <strong>Riemann Zeta function<\/strong> and the <strong>Hurwitz Zeta function<\/strong>. The <strong>Riemann Zeta function<\/strong> has an important part to play in understanding how prime numbers are distributed.<\/p>\n<p>The <strong>Hurwitz Zeta function<\/strong> generalizes the Riemann Zeta function, allowing it to accommodate a wider range of applications in fields like probability theory, quantum physics, and algebraic geometry. This tutorial will discuss how to make use of the <strong>zeta function<\/strong> in Python.<\/p>\n<h2><span class=\"ez-toc-section\" id=\"The_Riemann_Zeta_Function_in_Python\"><\/span><strong>The Riemann Zeta Function in Python<\/strong><span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>The <a href=\"https:\/\/en.wikipedia.org\/wiki\/Riemann_zeta_function\" target=\"_blank\" rel=\"noopener\"><strong>Riemann Zeta function<\/strong> <\/a>is significant in number theory and is denoted as <span class=\"katex-eq\" data-katex-display=\"false\">\\zeta(s)<\/span>. It is defined by the infinite series:<\/p>\n<span class=\"katex-eq\" data-katex-display=\"true\">\\zeta(s) = \\sum_{n=1}^{\\infty} \\frac{1}{n^s}<\/span>\n<p>where <span class=\"katex-eq\" data-katex-display=\"false\">s<\/span> is a <a href=\"https:\/\/tutorpython.com\/data-types-in-python\" target=\"_blank\" rel=\"noopener\">complex number<\/a>. One important application of the Riemann Zeta function is in investigating the distribution of prime numbers.<\/p>\n<p>The famous <strong>Riemann Hypothesis<\/strong> states that the non-trivial zeros of the zeta function lie on the critical line where <span class=\"katex-eq\" data-katex-display=\"false\">\\Re(s) = \\dfrac{1}{2}<\/span>.<\/p>\n<h3><span class=\"ez-toc-section\" id=\"Using_SciPy_to_compute_the_Riemann_Zeta_Function_in_Python\"><\/span><strong>Using SciPy to compute the Riemann Zeta Function in Python<\/strong><span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>The <a href=\"https:\/\/scipy.org\/\" target=\"_blank\" rel=\"nofollow noopener\"><code>scipy<\/code> library<\/a> in Python has an implementation of the Riemann Zeta function.<\/p>\n<p>This function can be accessed as <code>scipy.special.zeta<\/code> and is used to evaluate the zeta function for real and complex values of <span class=\"katex-eq\" data-katex-display=\"false\">s<\/span>.<\/p>\n<p>Here\u2019s a code example of the <code>scipy<\/code> in action:<\/p>\n<pre class=\"language-python line-numbers\"><code>import scipy.special as sp\r\n\r\n# Riemann Zeta function using SciPy\r\ns = 2  # Example value for s\r\nriemann_zeta = sp.zeta(s)\r\nprint(f\"Riemann Zeta function at s = {s}: {riemann_zeta}\")\r\n<\/code><\/pre>\n<p><strong>Output:<\/strong><\/p>\n<p>For <span class=\"katex-eq\" data-katex-display=\"false\">s = 2<\/span>, the output will be:<\/p>\n<p><img fetchpriority=\"high\" decoding=\"async\" class=\"aligncenter size-full wp-image-10151\" src=\"https:\/\/tutorpython.com\/wp-content\/uploads\/2023\/04\/output_riemann_zeta_function.png\" alt=\"output for Riemann zeta function in Python using scipy\" width=\"1200\" height=\"138\" srcset=\"https:\/\/tutorpython.com\/wp-content\/uploads\/2023\/04\/output_riemann_zeta_function.png 1200w, https:\/\/tutorpython.com\/wp-content\/uploads\/2023\/04\/output_riemann_zeta_function-300x35.png 300w, https:\/\/tutorpython.com\/wp-content\/uploads\/2023\/04\/output_riemann_zeta_function-1024x118.png 1024w, https:\/\/tutorpython.com\/wp-content\/uploads\/2023\/04\/output_riemann_zeta_function-768x88.png 768w, https:\/\/tutorpython.com\/wp-content\/uploads\/2023\/04\/output_riemann_zeta_function-600x69.png 600w\" sizes=\"(max-width: 1200px) 100vw, 1200px\" \/><\/p>\n<p>This value corresponds to the well-known result <span class=\"katex-eq\" data-katex-display=\"false\">\\zeta(2) = \\dfrac{\\pi^2}{6}<\/span>, which is central in number theory.<\/p>\n<h2><span class=\"ez-toc-section\" id=\"The_Hurwitz_Zeta_Function_in_Python\"><\/span><strong>The Hurwitz Zeta Function in Python<\/strong><span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>The <a href=\"https:\/\/mathworld.wolfram.com\/HurwitzZetaFunction.html\" target=\"_blank\" rel=\"nofollow noopener\"><strong>Hurwitz Zeta function<\/strong> <\/a>incorporates an additional parameter <span class=\"katex-eq\" data-katex-display=\"false\">q<\/span>, and is defined as:<\/p>\n<span class=\"katex-eq\" data-katex-display=\"true\">\\zeta(s, q) = \\sum_{n=0}^{\\infty} \\frac{1}{(n + q)^s}<\/span>\n<p>where <span class=\"katex-eq\" data-katex-display=\"false\">s<\/span> is a complex number and <span class=\"katex-eq\" data-katex-display=\"false\">q<\/span> is a real number with <span class=\"katex-eq\" data-katex-display=\"false\">q &gt; 0<\/span>.<\/p>\n<p>For the special case (when <span class=\"katex-eq\" data-katex-display=\"false\">q = 1<\/span>), the function becomes the <strong>Riemann Zeta function<\/strong>.<\/p>\n<p>Just like with the Riemann Zeta function, the Hurwitz Zeta function can be computed using the <code>scipy.special.zeta<\/code> function.<br \/>\nThis time, we will need to supply two <a href=\"https:\/\/tutorpython.com\/function-arguments-in-python\" target=\"_blank\" rel=\"nofollow noopener\">arguments<\/a>, <span class=\"katex-eq\" data-katex-display=\"false\">s<\/span> and <span class=\"katex-eq\" data-katex-display=\"false\">q<\/span>.<\/p>\n<p>See the code example below for how to call the <code>scipy.special.zeta<\/code> function:<\/p>\n<pre class=\"language-python line-numbers\"><code>import scipy.special as sp\r\n\r\n# Hurwitz Zeta function using SciPy\r\ns = 2  # Example value for s\r\nq = 1.5  # Example value for q\r\nhurwitz_zeta = sp.zeta(s, q)\r\nprint(f\"Hurwitz Zeta function at s = {s}, q = {q}: {hurwitz_zeta}\")\r\n<\/code><\/pre>\n<p><strong>Output:<\/strong><\/p>\n<p>For <span class=\"katex-eq\" data-katex-display=\"false\">s = 2<\/span> and <span class=\"katex-eq\" data-katex-display=\"false\">q = 1.5<\/span>, the output will be:<\/p>\n<p><img decoding=\"async\" class=\"aligncenter size-full wp-image-10152\" src=\"https:\/\/tutorpython.com\/wp-content\/uploads\/2023\/04\/output_hurwitz_zeta_function.png\" alt=\"output for Hurwitz zeta function in Python using scipy\" width=\"1247\" height=\"109\" srcset=\"https:\/\/tutorpython.com\/wp-content\/uploads\/2023\/04\/output_hurwitz_zeta_function.png 1247w, https:\/\/tutorpython.com\/wp-content\/uploads\/2023\/04\/output_hurwitz_zeta_function-300x26.png 300w, https:\/\/tutorpython.com\/wp-content\/uploads\/2023\/04\/output_hurwitz_zeta_function-1024x90.png 1024w, https:\/\/tutorpython.com\/wp-content\/uploads\/2023\/04\/output_hurwitz_zeta_function-768x67.png 768w, https:\/\/tutorpython.com\/wp-content\/uploads\/2023\/04\/output_hurwitz_zeta_function-600x52.png 600w\" sizes=\"(max-width: 1247px) 100vw, 1247px\" \/><\/p>\n<p>This computation reflects the generalized form of the zeta function, incorporating the shift parameter <span class=\"katex-eq\" data-katex-display=\"false\">q<\/span>, showcasing how the Hurwitz Zeta function extends the applicability of its Riemann counterpart.<\/p>\n<h2><span class=\"ez-toc-section\" id=\"Visualizing_the_Zeta_Function_with_Hurwitz_Generalization\"><\/span><strong>Visualizing the Zeta Function with Hurwitz Generalization<\/strong><span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>The Riemann Zeta function and its generalization, the Hurwitz Zeta function, provide insights into number theory and mathematical analysis.<\/p>\n<p>To visualize the behavior of these functions when <span class=\"katex-eq\" data-katex-display=\"false\">s<\/span> is real, we can plot the series for different values of the parameter <span class=\"katex-eq\" data-katex-display=\"false\">q<\/span>, showcasing the convergence patterns for each case.<\/p>\n<p>The Riemann Zeta function is given by the series:<\/p>\n<span class=\"katex-eq\" data-katex-display=\"true\">\\zeta(s) = \\sum_{n=1}^{\\infty} \\frac{1}{n^s}<\/span>\n<p>Expanding this:<\/p>\n<span class=\"katex-eq\" data-katex-display=\"true\">\\zeta(s) = \\frac{1}{1^s} + \\frac{1}{2^s} + \\frac{1}{3^s} + \\frac{1}{4^s} + \\dots<\/span>\n<p>This series starts at <span class=\"katex-eq\" data-katex-display=\"false\">n = 1<\/span> and sums over all positive integers.<\/p>\n<p>For <span class=\"katex-eq\" data-katex-display=\"false\">q = 2, 3, 5<\/span>, the Hurwitz Zeta function shifts the series by those values:<\/p>\n<span class=\"katex-eq\" data-katex-display=\"true\">\\zeta(s, 2) = \\sum_{n=0}^{\\infty} \\frac{1}{(n + 2)^s}<\/span>\n<span class=\"katex-eq\" data-katex-display=\"true\">\\zeta(s, 3) = \\sum_{n=0}^{\\infty} \\frac{1}{(n + 3)^s}<\/span>\n<span class=\"katex-eq\" data-katex-display=\"true\">\\zeta(s, 5) = \\sum_{n=0}^{\\infty} \\frac{1}{(n + 5)^s}<\/span>\n<p>Expanding these, we get the infinite series:<\/p>\n<span class=\"katex-eq\" data-katex-display=\"true\">\\zeta(s, 2) = \\frac{1}{2^s} + \\frac{1}{3^s} + \\frac{1}{4^s} + \\frac{1}{5^s} + \\dots<\/span>\n<span class=\"katex-eq\" data-katex-display=\"true\">\\zeta(s, 3) = \\frac{1}{3^s} + \\frac{1}{4^s} + \\frac{1}{5^s} + \\frac{1}{6^s} + \\dots<\/span>\n<span class=\"katex-eq\" data-katex-display=\"true\">\\zeta(s, 5) = \\frac{1}{5^s} + \\frac{1}{6^s} + \\frac{1}{7^s} + \\frac{1}{8^s} + \\dots<\/span>\n<p>We can now visualize how the Riemann Zeta function (<span class=\"katex-eq\" data-katex-display=\"false\">q = 1<\/span>) and Hurwitz Zeta functions (<span class=\"katex-eq\" data-katex-display=\"false\">q = 2, 3, 5<\/span>) behave for different real values of <span class=\"katex-eq\" data-katex-display=\"false\">s<\/span> using Python. These plots will provide insights into how the growth of these functions changes as <span class=\"katex-eq\" data-katex-display=\"false\">q<\/span> increases and highlight the critical vertical asymptotes at <span class=\"katex-eq\" data-katex-display=\"false\">s = 1<\/span>.<\/p>\n<p>To compute the values of the Riemann and Hurwitz Zeta functions, we use <code>mpmath<\/code> instead of <code>scipy<\/code>. <code>scipy.special.zeta<\/code> has known limitations when computing values for real numbers between <span class=\"katex-eq\" data-katex-display=\"false\">0<\/span> and <span class=\"katex-eq\" data-katex-display=\"false\">1<\/span> when the value of <span class=\"katex-eq\" data-katex-display=\"false\">q<\/span> is specified.<\/p>\n<p>For instance, calling <code>scipy.special.zeta(1\/2, 1)<\/code> incorrectly returns <code>NaN<\/code> due to how the Hurwitz Zeta function is defined in <code>scipy<\/code>, even though the correct value should be approximately <span class=\"katex-eq\" data-katex-display=\"false\">-1.46<\/span>.<\/p>\n<p>In contrast, <code>mpmath<\/code> supports the full analytic continuation of the zeta function and provides high-precision results, making it more reliable for computations across the entire range of real and complex inputs.<\/p>\n<pre class=\"language-python line-numbers\"><code>import numpy as np\r\nimport matplotlib.pyplot as plt\r\nfrom mpmath import zeta\r\n\r\ndef calculate_zeta_values(s_values, q=1):\r\n    return [zeta(s, q) for s in s_values]\r\n\r\ndef plot_zeta_function(ax, s_neg, s_pos, q, color, label):\r\n    # Calculate the zeta values for both subdomains\r\n    zeta_neg = calculate_zeta_values(s_neg, q)\r\n    zeta_pos = calculate_zeta_values(s_pos, q)\r\n    \r\n    # Plot the values for both subdomains with the same label\r\n    ax.plot(s_neg, zeta_neg, color=color)\r\n    ax.plot(s_pos, zeta_pos, color=color, label=label)\r\n\r\n    # Add asymptote at s = 1\r\n    ax.axvline(x=1, color='gray', linestyle='--')  # Asymptote at s = 1\r\n    ax.set_xlabel('s (Real part)')\r\n    ax.set_ylabel(r'$\\zeta(s, q)$')\r\n    ax.legend()\r\n    ax.grid(True)\r\n    ax.set_ylim(-10, 10)  # Adjust y-limits for better visualization\r\n\r\ndef visualize_zeta_functions():\r\n    # Define real part of s, avoiding s = 1 and close values\r\n    s_neg = np.linspace(0.1, 0.9, 500)  # From 0.1 to 0.9\r\n    s_pos = np.linspace(1.1, 5, 500)    # From 1.1 to 5\r\n    \r\n    # Initialize a 2x2 grid of subplots\r\n    fig, axs = plt.subplots(2, 2, figsize=(14, 10))\r\n\r\n    # Plot Riemann Zeta function (q=1)\r\n    plot_zeta_function(axs[0, 0], s_neg, s_pos, q=1, color='blue', label=r'Riemann $\\zeta(s)$')\r\n\r\n    # Plot Hurwitz Zeta function for q=2, q=3, q=5\r\n    plot_zeta_function(axs[0, 1], s_neg, s_pos, q=2, color='orange', label=r'Hurwitz $\\zeta(s, 2)$')\r\n    plot_zeta_function(axs[1, 0], s_neg, s_pos, q=3, color='green', label=r'Hurwitz $\\zeta(s, 3)$')\r\n    plot_zeta_function(axs[1, 1], s_neg, s_pos, q=5, color='red', label=r'Hurwitz $\\zeta(s, 5)$')\r\n\r\n    # Set titles for each subplot\r\n    axs[0, 0].set_title('Riemann Zeta Function (q=1)')\r\n    axs[0, 1].set_title('Hurwitz Zeta Function (q=2)')\r\n    axs[1, 0].set_title('Hurwitz Zeta Function (q=3)')\r\n    axs[1, 1].set_title('Hurwitz Zeta Function (q=5)')\r\n\r\n    # Adjust layout to prevent overlap\r\n    plt.tight_layout()\r\n    \r\n    # Show the plot\r\n    plt.show()\r\n\r\n# Visualize the plots\r\nvisualize_zeta_functions()\r\n<\/code><\/pre>\n<p>The provided script visualizes both the Riemann Zeta function and the Hurwitz Zeta function for different values of the parameter <span class=\"katex-eq\" data-katex-display=\"false\">q<\/span>. The function values are plotted for two distinct subdomains: one where <span class=\"katex-eq\" data-katex-display=\"false\">0 &lt; s &lt; 1<\/span>. These ranges were chosen to avoid the singularity that occurs at <span class=\"katex-eq\" data-katex-display=\"false\">s = 1<\/span>, where the Zeta function diverges. The <a href=\"https:\/\/mpmath.org\/\" target=\"_blank\" rel=\"nofollow noopener\"><code>mpmath<\/code> library<\/a> is used to compute the Zeta function values for both the Riemann case <span class=\"katex-eq\" data-katex-display=\"false\">(q = 1)<\/span> and the Hurwitz cases with <span class=\"katex-eq\" data-katex-display=\"false\">(q = 2, 3, 5)<\/span>. Each function is plotted in a different subplot for clear comparison.<\/p>\n<p>The reason for splitting the real values of <span class=\"katex-eq\" data-katex-display=\"false\">s<\/span> into two subdomains is to properly handle the asymptote at <span class=\"katex-eq\" data-katex-display=\"false\">s=1<\/span>. Without dividing the range, <code>matplotlib<\/code> would attempt to connect the values on both sides of <span class=\"katex-eq\" data-katex-display=\"false\">s=1<\/span>, which would cause the plot to incorrectly smooth over the singularity and misrepresent the behavior of the function.<\/p>\n<p>By splitting the domain, the plot ensures that the asymptote is clearly visible, and a vertical dashed line is added at <span class=\"katex-eq\" data-katex-display=\"false\">s=1<\/span> to indicate the divergence, ensuring proper visualization of the Zeta function&#8217;s distinct behavior in each subdomain.<\/p>\n<p><strong>Output:<\/strong><br \/>\n<img decoding=\"async\" class=\"aligncenter size-full wp-image-10125\" src=\"https:\/\/tutorpython.com\/wp-content\/uploads\/2023\/04\/python-zeta-visualization-mpmath.png\" alt=\"python zeta visualization mpmath and matplotlib\" width=\"1389\" height=\"989\" srcset=\"https:\/\/tutorpython.com\/wp-content\/uploads\/2023\/04\/python-zeta-visualization-mpmath.png 1389w, https:\/\/tutorpython.com\/wp-content\/uploads\/2023\/04\/python-zeta-visualization-mpmath-300x214.png 300w, https:\/\/tutorpython.com\/wp-content\/uploads\/2023\/04\/python-zeta-visualization-mpmath-1024x729.png 1024w, https:\/\/tutorpython.com\/wp-content\/uploads\/2023\/04\/python-zeta-visualization-mpmath-768x547.png 768w, https:\/\/tutorpython.com\/wp-content\/uploads\/2023\/04\/python-zeta-visualization-mpmath-600x427.png 600w\" sizes=\"(max-width: 1389px) 100vw, 1389px\" \/><\/p>\n<p>The visualizations of the Riemann and Hurwitz Zeta functions with different <span class=\"katex-eq\" data-katex-display=\"false\">q<\/span>-values highlight several key insights.<\/p>\n<p>A vertical asymptote at <span class=\"katex-eq\" data-katex-display=\"false\">s = 1<\/span> is visible in all plots, indicating the point where the Zeta function becomes undefined.<\/p>\n<p>This asymptotic behavior is consistent across both the Riemann and Hurwitz Zeta functions. In the range <span class=\"katex-eq\" data-katex-display=\"false\">0 &lt; s &lt; 1<\/span>, the function rapidly decreases to negative infinity as <span class=\"katex-eq\" data-katex-display=\"false\">s<\/span> approaches <span class=\"katex-eq\" data-katex-display=\"false\">1<\/span> from the left, with the rate of decrease slightly varying based on <span class=\"katex-eq\" data-katex-display=\"false\">q<\/span>.<\/p>\n<p>In conclusion, the Python libraries <code>scipy<\/code> and <code>mpmath<\/code> provide accessible implementations for both the Riemann and Hurwitz Zeta functions.<\/p>\n<p>These tools allow users to explore complex mathematical concepts such as prime distribution and generalized Zeta functions straightforwardly.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>The Zeta function encompasses a family of important mathematical functions, primarily including&#8230;<\/p>\n","protected":false},"author":81,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[28],"tags":[],"class_list":["post-8133","post","type-post","status-publish","format-standard","hentry","category-tutorial"],"acf":[],"_links":{"self":[{"href":"https:\/\/tutorpython.com\/wp-json\/wp\/v2\/posts\/8133","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/tutorpython.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/tutorpython.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/tutorpython.com\/wp-json\/wp\/v2\/users\/81"}],"replies":[{"embeddable":true,"href":"https:\/\/tutorpython.com\/wp-json\/wp\/v2\/comments?post=8133"}],"version-history":[{"count":15,"href":"https:\/\/tutorpython.com\/wp-json\/wp\/v2\/posts\/8133\/revisions"}],"predecessor-version":[{"id":10309,"href":"https:\/\/tutorpython.com\/wp-json\/wp\/v2\/posts\/8133\/revisions\/10309"}],"wp:attachment":[{"href":"https:\/\/tutorpython.com\/wp-json\/wp\/v2\/media?parent=8133"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/tutorpython.com\/wp-json\/wp\/v2\/categories?post=8133"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/tutorpython.com\/wp-json\/wp\/v2\/tags?post=8133"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}