Skip to content
Permalink
main
Switch branches/tags

Name already in use

A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
Go to file
 
 
Cannot retrieve contributors at this time
{
"cells": [
{
"cell_type": "markdown",
"id": "ee2658f8-70c5-41e5-93ba-bd5e2a108ec5",
"metadata": {},
"source": [
"This notebook provides a few examples of floating point exceptions in Python. These examples showcase various scenarios where floating-point exceptions can occur, such as overflow, underflow, not-a-number (NaN) results, inexact representations, and catastraphic cancellation due to limited precision. Finally, an exercise to read in data and visualize result is provided.\n",
" \n",
" Xinyu Zhao, Fall 2023, ME3275"
]
},
{
"cell_type": "markdown",
"id": "1b414213-8669-4944-bab1-288d9a8e5fed",
"metadata": {},
"source": [
"First, let us import all the necessary libraries for Python.\n",
"Numpy is used for array operations, math has commonly used mathematical functions and matplotlib provides necessary tools to plot functions in this tutorial."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "8ec31a27-81cd-425a-83cc-25499e7d8665",
"metadata": {},
"outputs": [],
"source": [
"import numpy as np\n",
"import math\n",
"import matplotlib.pyplot as plt"
]
},
{
"cell_type": "markdown",
"id": "ae1d64c7-7986-4b26-ab7d-bc9f3f053f76",
"metadata": {},
"source": [
"When you run the following code, you'll get a \"ZeroDivisionError: float division by zero\" exception, which is a type of floating-point exception. This occurs because you're attempting to divide by zero, which is not a valid operation in mathematics or programming."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "937fcfef-9054-4fee-8c9a-863307b102a2",
"metadata": {},
"outputs": [],
"source": [
"result = 1.0 / 0.0\n",
"print(result)"
]
},
{
"cell_type": "markdown",
"id": "84b2d4e9-9e38-4e12-8cb2-007fdffb5d02",
"metadata": {},
"source": [
"The following code will result in an \"OverflowError: math range error\" since the result of math.exp(1000) is too large to be represented as a floating-point number."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "1b789f7b-6216-43aa-a1f2-87f4563be158",
"metadata": {},
"outputs": [],
"source": [
"result = math.exp(1000)\n",
"print(result)"
]
},
{
"cell_type": "markdown",
"id": "7c20110a-c48a-4634-b95e-3758043a4ad1",
"metadata": {},
"source": [
"Interestingly, if you run the same function with numpy, you will get an infinity answer and only get an overflow warning, like the following. A warning would not interrupt a series of operation while \"an error\" would stop the flow of commands when you have a series of operations. This can be beneficial sometimes when computer codes correct its own mistake later. "
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "011f3476-37cd-4a46-89f5-420e2e607ba1",
"metadata": {},
"outputs": [],
"source": [
"result = np.exp(1000)\n",
"print(result)"
]
},
{
"cell_type": "markdown",
"id": "6131549d-8456-4391-8020-c3a42c660d81",
"metadata": {},
"source": [
"Underflow: This will result in a very small value close to zero, indicating an underflow situation where the result is too close to zero to be accurately represented as a floating-point number."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "d89aa2e3-4543-4ada-8e97-26706835b7d4",
"metadata": {},
"outputs": [],
"source": [
"result = 1.0 / math.exp(1000)\n",
"print(result)"
]
},
{
"cell_type": "markdown",
"id": "752a69a7-c813-43d6-bc1c-c217acf55121",
"metadata": {},
"source": [
"NAN: creating an undefined number will result in a NaN value (Not a Number). NaN is a special value that represents the result of undefined or indeterminate mathematical operations."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "6e4199fb-80bc-47f4-975b-d4dc3cc612ea",
"metadata": {},
"outputs": [],
"source": [
"result = np.inf*0\n",
"print(result)"
]
},
{
"cell_type": "markdown",
"id": "eaf21054-e5fd-420d-83c6-3a8213f2b914",
"metadata": {},
"source": [
"Inaccurate values: the following expression will result in an approximation of 0.3333333... due to the limited precision of floating-point arithmetic, resulting in an inexact representation of the actual result."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "f78c1608-3fb9-4af8-a780-00940d79880a",
"metadata": {},
"outputs": [],
"source": [
"result = 1.0 / 3.0\n",
"print(result)"
]
},
{
"cell_type": "markdown",
"id": "d69c2e71-68c1-418e-9baf-c50fcf10e458",
"metadata": {},
"source": [
"We have discussed in class that many of the numbers cannot be represented exactly, so that if you use them in logic flow, you may end up with unexpected results: for example, "
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "70a5e5f3-b3a1-49da-85f7-acfe2338e8b3",
"metadata": {},
"outputs": [],
"source": [
"if 0.1+0.2==0.3:\n",
" a=1\n",
"else:\n",
" a=0\n",
"print(a)\n",
"b=0.1+0.2\n",
"print(b)\n",
"c=0.3\n",
"print(c)"
]
},
{
"cell_type": "markdown",
"id": "608806f2-2a3a-4a5b-9c88-5cd9d323cd60",
"metadata": {},
"source": [
"The following if-else statement would actually lead to a different result. Try it yourself. Due to this \"uncertainty\" in how approximation is handled, it is recommended that floating point arithmetic should not be used in logic flows such as if/else and while, etc. "
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "440dc92a-2d91-42de-897f-8cd1bb289b4d",
"metadata": {},
"outputs": [],
"source": [
"if 0.1+0.3==0.4:\n",
" a=1\n",
"else:\n",
" a=0\n",
"print(a)\n",
"b=0.1+0.3\n",
"print(b)\n",
"c=0.4\n",
"print(c)"
]
},
{
"cell_type": "markdown",
"id": "a7f42db6-91b8-4d0a-a592-7b9e86baa8fe",
"metadata": {},
"source": [
"Catastrophic cancelation: when subtractions are performed with nearly equal operands, sometimes cancellation can occur unexpectedly. The following is an example of a cancellation."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "743e99c6-6eea-4f14-b4cc-ccbde0c38010",
"metadata": {},
"outputs": [],
"source": [
"a = 1.234567890123456789\n",
"b = 1.234567890123456788\n",
"result = a - b\n",
"print(result)"
]
},
{
"cell_type": "markdown",
"id": "408d41e5-f56f-46b5-9e1c-188cac69b59b",
"metadata": {},
"source": [
"Catastrophic cancelation in a function can cause unexpected fluctuations. When both the denominator and numerator are approaching zero at the same rate, the following function should approach 1. "
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "6edc63a4-240f-4682-8ea2-b4e62401a73c",
"metadata": {},
"outputs": [],
"source": [
"x = 1e-8\n",
"result = (math.exp(x) - 1) / x\n",
"print(result)"
]
},
{
"cell_type": "markdown",
"id": "f0a02797-e057-442f-a8e8-f4389e515295",
"metadata": {},
"source": [
"Now let's plot this function near x=0 between [-1E-8,1E-8] and see what happens."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "417d0e7d-8aef-4294-a9b3-086c5746b29b",
"metadata": {},
"outputs": [],
"source": [
"\n",
"# Define the function\n",
"def example_function(x):\n",
" return (np.exp(x) - 1) / x\n",
"\n",
"# Generate x values\n",
"x_values = np.linspace(-1e-8, 1e-8, 400)\n",
"\n",
"# Calculate corresponding y values\n",
"y_values = example_function(x_values)\n",
"\n",
"# Create the plot\n",
"plt.figure(figsize=(8, 6))\n",
"plt.plot(x_values, y_values, label='(exp(x) - 1) / x')\n",
"plt.axhline(y=1, color='r', linestyle='--', label='Expected value: 1')\n",
"plt.xlabel('x')\n",
"plt.ylabel('y')\n",
"plt.title('Function with Catastrophic Cancellation')\n",
"plt.legend()\n",
"plt.grid()\n",
"plt.show()\n"
]
},
{
"cell_type": "markdown",
"id": "1cdf0da6-567e-485b-907c-6cbacc40e3b5",
"metadata": {},
"source": [
"For the last exercise, let's read in some data stored in binary format and finally save it in platform independent way with np.save(). Download the data file (velocity.dat) from this dropbox link: https://www.dropbox.com/s/q4q2xc5xxktiv2j/velocity.dat?dl=0. The data file is a y-direction velocity component output file from a direct numerical simulation (DNS) of a turbulent flame. The mesh of the computational domain has 920 grid points in x direction, 1400 grid points in y direction, 720 grid points in z direction. The grid spacing is uniform in all three directions, i.e., dx = dy = dz = 0.026 mm. In the y-component velocity output file, a single-precision (32 bit) y-velocity value is stored for each grid point. The data is stored with little-endian format."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "9d8c0337-b797-455b-8b7f-12c2e58bd5f3",
"metadata": {},
"outputs": [],
"source": [
"# Let's first compute the total number of grid points N in the mesh\n",
"N = #your input\n",
"\n",
"# The total number of data entries is the same as the total number of grid point. Therefore the size of the file should be \n",
"file_size = #your input"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "fc24ede1-2253-4965-a335-d548d98c71a5",
"metadata": {},
"outputs": [],
"source": [
"read_file_name = \"/Users/xiz14026/Dropbox/velocity.dat\"\n",
"yVel = np.fromfile(read_file_name, dtype = np.dtype('<f4'), sep = \"\")\n",
"yVel_3D=yVel.reshape((720,1400,920))\n",
"#plot the velocity contour at the central z plane\n",
"\n",
"#generate 2D grid with 920 points in the x direction and 1400 points in the y direction\n",
"xlist = #your input\n",
"ylist = #your input\n",
"X, Y = np.meshgrid(xlist, ylist)\n",
"\n",
"#plot the central slice as a 2D contour plot\n",
"fig,ax=plt.subplots(1,1)\n",
"cp = ax.contourf(X, Y, yVel_3D[360,:,:])\n",
"# Add a colorbar to a plot\n",
"# your input\n",
"# Add a title and x and y axis lables\n",
"# your input\n",
"plt.show()"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "976b46d9-e69a-4fde-844c-598b528e43a2",
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.11.5"
}
},
"nbformat": 4,
"nbformat_minor": 5
}