std::midpoint in C++
The C++ Standard Library includes numerous tools for manipulating numbers, and std::midpoint is a valuable addition to this toolkit. Introduced in C++20, this function calculates the midpoint between two values and exhibits robust behavior when operating with integers, floating-point numbers, and even pointers. This tutorial delves into the features, nuances, and practical applications of std::midpoint.
Midpoint Function
Fundamentally, std::midpoint calculates the mean of two parameters, a and b. However, it goes beyond the straightforward (a + b) / 2 formula. It is what makes it unique:
- Overflow Prevention: When working with numbers, adding can lead to overflow. The std::midpoint method prevents this by employing sophisticated methods to ensure that the result remains inside the representable range of the return type.
- Rounding for Integers: If a and b are integers and their total is odd, the midpoint is rounded towards a. By doing this, consistent behavior with discrete values is ensured.
- Minimal Floating-Point Inexactness: Although there will always be some rounding mistakes in floating-point computations, std::midpoint aims to compute with a maximum of one such imprecise operation.
- Pointer Arithmetic: When both arguments are pointers to elements within the same array, std::midpoint acts as a pointer arithmetic shortcut. It returns a pointer to the element at the midpoint between the original elements.
When to use std::midpoint?
The std::midpoint boasts two overloads, catering to different argument types:
Overload 1: Arithmetic Types (except bool)
This overload supports both floating-point and integer data types. For integers, it ensures no overflow, and for floating-point values, it ensures few rounding mistakes.
Syntax:
The syntax is as follows:
template <typename T>
constexpr T midpoint(T a, T b);
Example:
Let us take an example to illustrate the std::midpoint using arithmetic types in C++.
#include <iostream>
template<typename T>
constexpr T midpoint(const T& a, const T& b) noexcept {
return a + (b - a) / 2;
}
int main() {
// Instance 1: Midpoint of integers
int x = 5, y = 12;
int mid = midpoint(x, y); // mid will be 7 (rounded towards x)
std::cout << "Midpoint of integers: " << mid << std::endl;
// Instance 2: Midpoint of floating-point numbers
double a = 3.5, b = 4.7;
double center = midpoint(a, b); // center might be slightly inexact
std::cout << "Midpoint of floating-point numbers: " << center << std::endl;
return 0;
}
Output:
![std::midpoint in C++/>
<!-- /wp:html -->
<!-- wp:heading {](https://static.tutorialandexample.com/cpp/std-midpoint-in-cpp1.png)
Overload 2: Object Types
When both arguments are pointers to items in the same array, this overload is applicable. Under the hood, pointer arithmetic is used to determine the pointer to the midpoint element.
Syntax:
It has the following syntax:
template <typename T>
constexpr T* midpoint(T* a, T* b);
Example:
Let us take an example to illustrate the std::midpoint using object types in C++.
#include <iostream>
#include <algorithm> // for std::midpoint
template<typename T>
constexpr T* midpoint(T* begin, T* end) noexcept {
return begin + (end - begin) / 2;
}
int main() {
int arr[] = {1, 3, 5, 7, 9};
int* mid_ptr = midpoint(arr, arr + 4); // mid_ptr points to arr[2] (value: 5)
std::cout << "Value at midpoint: " << *mid_ptr << std::endl;
return 0;
}
Output:
![std::midpoint in C++/>
<!-- /wp:html -->
<!-- wp:heading {](https://static.tutorialandexample.com/cpp/std-midpoint-in-cpp2.png)
Performance considerations:
If its arguments are constexpr, it can be evaluated at build time because std::midpoint is a constexpr function. It may result in situations where the arguments are known at compile time, perhaps improving performance.