Define your piecewise function below. Each piece consists of a formula and its corresponding interval.
<input type="text" id="interval1" placeholder="e.g., x < 2" value="x
<input type="text" id="interval2" placeholder="e.g., 2 <= x = 0″>
5″ value="x > 2″>
Graph Visualization
Define your functions and intervals to see the graph.
Understanding Piecewise Defined Functions
A piecewise defined function is a function defined by multiple sub-functions, each applying to a certain interval of the main function's domain. In simpler terms, it's like having several different functions, and you choose which one to use based on the input value (x).
Mathematical Definition
A piecewise function \(f(x)\) can be formally written as:
Where \(f_1, f_2, \dots, f_n\) are different function expressions, and \(I_1, I_2, \dots, I_n\) are the corresponding intervals (or conditions) on the domain of \(x\). The union of these intervals must cover the entire domain for which the function is defined, and typically, these intervals are disjoint or meet at specific points.
Key Components:
Function Expressions: These are the standard mathematical formulas (e.g., \(x^2\), \(2x+1\), \(\sin(x)\)) that define the output of the function for a given input within a specific interval.
Intervals: These are the conditions that determine which function expression to use. They are typically expressed using inequalities involving the input variable (e.g., \(x 5\)).
Graphing Piecewise Functions
To graph a piecewise function, you follow these steps:
Graph each piece separately: For each sub-function (\(f_i(x)\)), graph it as if it were a regular function.
Apply the interval constraints: Once you have the graph of a sub-function, you only keep the part of the graph that falls within its specified interval (\(I_i\)). Points exactly at the boundary of an interval need careful consideration:
If the interval includes the endpoint (e.g., \(x \le 2\)), the point is typically plotted as a solid circle.
If the interval excludes the endpoint (e.g., \(x < 2\)), the point is typically plotted as an open circle.
Combine the pieces: The final graph is the collection of all the valid segments from each piece.
Use Cases
Piecewise functions are incredibly useful in real-world modeling:
Cost Analysis: A company might charge different rates for electricity based on consumption tiers (e.g., first 100 kWh at one price, next 200 kWh at a higher price).
Tax Brackets: Income tax systems often use piecewise functions where different portions of income are taxed at different rates.
Engineering: Designing systems with different operating modes or thresholds.
Computer Science: Algorithms whose behavior changes based on input size or other conditions.
This calculator helps visualize these functions by plotting them across a specified range, allowing users to better understand their behavior and the transitions between different function definitions.
// Function to evaluate a mathematical expression safely
function evaluateExpression(expression, x) {
try {
// Basic sanitization and replacement for 'x'
expression = expression.replace(/x/g, `(${x})`);
// Use a limited set of Math functions for security
var allowedMath = [
'Math.sin', 'Math.cos', 'Math.tan', 'Math.sqrt',
'Math.abs', 'Math.pow', 'Math.log', 'Math.exp',
'Math.PI', 'Math.E'
];
var sanitizedExpression = expression.replace(/(Math\.\w+)/g, function(match) {
return allowedMath.includes(match) ? match : 'undefined';
});
// Prevent dangerous characters or keywords
if (/[^0-9.+\-*/^()=xE]/.test(sanitizedExpression.replace(/\s/g, "))) {
// Allow common math symbols and numbers, x, E
return NaN; // Indicate an invalid expression
}
// Replace '^' with 'Math.pow' for exponentiation
var finalExpression = sanitizedExpression.replace(/\^/g, 'Math.pow');
// Evaluate the expression. Use Function constructor for dynamic evaluation
// within a controlled environment.
var result = new Function('x', `with(Math){ return ${finalExpression}; }`)(x);
// Check if the result is a valid number
if (typeof result === 'number' && isFinite(result)) {
return result;
} else {
return NaN;
}
} catch (e) {
console.error("Error evaluating expression:", expression, e);
return NaN; // Return NaN if there's any error during evaluation
}
}
// Function to parse and evaluate interval conditions
function evaluateInterval(intervalStr, x) {
try {
// Replace x with its value, then evaluate the condition
var condition = intervalStr.replace(/x/g, `(${x})`);
// Use eval cautiously, assuming intervalStr is controlled or simple
// Basic checks to prevent abuse
if (/[^0-9.+\-*/() =]/.test(condition.replace(/\s/g, "))) {
return false; // Invalid characters in interval
}
return new Function(`return ${condition};`)();
} catch (e) {
console.error("Error evaluating interval:", intervalStr, e);
return false;
}
}
// Function to plot the piecewise function
function plotFunction() {
var canvas = document.getElementById("graphCanvas");
var ctx = canvas.getContext("2d");
// Get input values
var formulas = [
document.getElementById("formula1").value,
document.getElementById("formula2").value,
document.getElementById("formula3").value
];
var intervals = [
document.getElementById("interval1").value,
document.getElementById("interval2").value,
document.getElementById("interval3").value
];
var xMin = parseFloat(document.getElementById("xMin").value);
var xMax = parseFloat(document.getElementById("xMax").value);
var yMin = parseFloat(document.getElementById("yMin").value);
var yMax = parseFloat(document.getElementById("yMax").value);
var resolution = parseInt(document.getElementById("resolution").value);
var messageDiv = document.getElementById("resultMessage");
// Validate numerical inputs
if (isNaN(xMin) || isNaN(xMax) || isNaN(yMin) || isNaN(yMax) || isNaN(resolution) ||
xMin >= xMax || yMin >= yMax || resolution <= 0) {
messageDiv.innerHTML = "Error: Please enter valid numerical ranges and resolution.";
return;
}
// Clear previous drawing
ctx.clearRect(0, 0, canvas.width, canvas.height);
// Set canvas dimensions to fit container
var graphContainer = document.getElementById("graphContainer");
canvas.width = graphContainer.clientWidth;
canvas.height = graphContainer.clientHeight;
// — Coordinate System Setup —
var plotWidth = canvas.width – 40; // Subtract padding
var plotHeight = canvas.height – 40; // Subtract padding
var originX = (0 – xMin) / (xMax – xMin) * plotWidth + 20;
var originY = plotHeight – ((0 – yMin) / (yMax – yMin) * plotHeight) + 20;
// Function to transform x-coordinate from data space to canvas space
var transformX = function(xData) {
return ((xData – xMin) / (xMax – xMin)) * plotWidth + 20;
};
// Function to transform y-coordinate from data space to canvas space
var transformY = function(yData) {
return plotHeight – (((yData – yMin) / (yMax – yMin)) * plotHeight) + 20;
};
// Function to transform x-coordinate from canvas space to data space
var inverseTransformX = function(xCanvas) {
return xMin + (xCanvas – 20) / plotWidth * (xMax – xMin);
};
// Function to transform y-coordinate from canvas space to data space
var inverseTransformY = function(yCanvas) {
return yMin + (plotHeight – (yCanvas – 20)) / plotHeight * (yMax – yMin);
};
// — Draw Axes —
ctx.strokeStyle = "#cccccc";
ctx.lineWidth = 1;
// X-axis
if (yMin = 0) {
var xAxisY = transformY(0);
ctx.beginPath();
ctx.moveTo(20, xAxisY);
ctx.lineTo(canvas.width – 20, xAxisY);
ctx.stroke();
}
// Y-axis
if (xMin = 0) {
var yAxisX = transformX(0);
ctx.beginPath();
ctx.moveTo(yAxisX, 20);
ctx.lineTo(yAxisX, canvas.height – 20);
ctx.stroke();
}
// — Draw Grid Lines (Optional) —
ctx.strokeStyle = "#eeeeee";
ctx.lineWidth = 0.5;
// Vertical grid lines
var xStep = (xMax – xMin) / 10;
for (var i = 1; i < 10; i++) {
var gridX = transformX(xMin + i * xStep);
ctx.beginPath();
ctx.moveTo(gridX, 20);
ctx.lineTo(gridX, canvas.height – 20);
ctx.stroke();
}
// Horizontal grid lines
var yStep = (yMax – yMin) / 10;
for (var i = 1; i < 10; i++) {
var gridY = transformY(yMin + i * yStep);
ctx.beginPath();
ctx.moveTo(20, gridY);
ctx.lineTo(canvas.width – 20, gridY);
ctx.stroke();
}
// — Plot the Function —
ctx.lineWidth = 2;
var step = (xMax – xMin) / resolution;
var plottedSuccessfully = false;
for (var i = 0; i < formulas.length; i++) {
var formula = formulas[i];
var interval = intervals[i];
if (!formula || !interval) continue; // Skip if empty
ctx.strokeStyle = getColor(i); // Assign a color to each function piece
ctx.beginPath();
var firstPoint = true;
for (var j = 0; j = yMin && y <= yMax) {
var canvasX = transformX(x);
var canvasY = transformY(y);
if (firstPoint) {
ctx.moveTo(canvasX, canvasY);
firstPoint = false;
plottedSuccessfully = true; // Mark that at least one point was plotted
} else {
ctx.lineTo(canvasX, canvasY);
}
} else {
// If y is out of bounds or NaN, break the current line segment
// and start a new one if possible
if (!firstPoint) {
ctx.stroke(); // Finish the current segment
ctx.beginPath(); // Start a new path
firstPoint = true;
}
}
} else {
// If x is outside the interval, break the current line segment
if (!firstPoint) {
ctx.stroke(); // Finish the current segment
ctx.beginPath(); // Start a new path
firstPoint = true;
}
}
}
// Draw the last segment
if (!firstPoint) {
ctx.stroke();
}
}
if (!plottedSuccessfully) {
messageDiv.innerHTML = "Note: No points were plotted within the specified range and conditions. Check your formulas and intervals.";
} else {
messageDiv.innerHTML = "Graph plotted successfully!";
}
}
// Helper function to get distinct colors
var colors = ["#004a99", "#28a745", "#ffc107", "#dc3545", "#6f42c1", "#fd7e14"];
function getColor(index) {
return colors[index % colors.length];
}
// Initial plot on load
window.onload = function() {
plotFunction();
};