What algorithm from the standard C ++ library can be used to calculate the module of the maximum modulo element from a given set?

    2 answers 2

    max_element , certainly. With your comparator.

     using namespace std; int a[] = { -5, 2, 3, 8, -10, 6, 7, 4 }; auto x = max_element(begin(a),end(a),[](int a, int b) { return abs(a) < abs(b); }); cout << abs(*x) << endl; 

      To solve your problem, two standard algorithms may be suitable, both of which are declared in the header file <algorithm> . This is the std::max algorithm, which takes an object of type std::initializer_list as an argument. He has the following announcement

       template<class T, class Compare> constexpr T max(initializer_list<T> t, Compare comp); 

      This algorithm returns the maximum value.

      And the second algorithm is the std::max_element , which takes iterators as arguments and returns an iterator pointing to the element with the maximum value according to the specified condition of element comparison. This algorithm has the following declaration.

       template<class ForwardIterator, class Compare> ForwardIterator max_element(ForwardIterator first, ForwardIterator last, Compare comp); 

      When you want to find the maximum element or the maximum value of the elements in absolute value, one problem arises, which many programmers forget. The fact is that for numbers that have a complement to 2, as is the case with most compilers, if you apply a function, for example, to an object of type int that has a minimum negative value, then the std::abs function will return a negative value! Naturally, this negative value will be less than any positive value or zero, although from a mathematical point of view, the absolute value of this minimum negative value must be at least greater than 0.

      Consider the following simple example.

       #include <iostream> #include <iomanip> #include <cstdlib> #include <limits> int main() { int min = std::numeric_limits<int>::min(); int max = std::numeric_limits<int>::max(); std::cout << "min = " << min << std::endl; std::cout << "max = " << max << std::endl; std::cout << "std::abs( min ) < 0 is " << std::boolalpha << (std::abs(min) < 0) << std::endl; } 

      The output of the program to the console will be as follows.

       min = -2147483648 max = 2147483647 std::abs( min ) < 0 is true 

      As you can see, it turned out that std::abs( min ) less than zero, although it is obvious from a mathematical point of view that the absolute value of -2147483648 is not only greater than 0, but even greater than the maximum value 2147483647 that can be stored in int objects . Therefore, for sequences with integer values, using the standard function std::abs can lead to an incorrect result.

      How to get out of this situation? For integer values, it is better to compare the two values ​​as negative values. For example, consider the use of the std::max algorithm.

       #include <iostream> #include <iomanip> #include <algorithm> #include <cstdlib> #include <limits> int main() { auto max_abs1 = [](int x, int y) { return std::abs(x) < std::abs(y); }; int maximum = std::max({ std::numeric_limits<int>::min(), std::numeric_limits<int>::max() }, max_abs1); std::cout << "maximum = " << maximum << std::endl; auto max_abs2 = [](int x, int y) { return (y < 0 ? y : -y) < (x < 0 ? x : -x); }; maximum = std::max({ std::numeric_limits<int>::min(), std::numeric_limits<int>::max() }, max_abs2); std::cout << "maximum = " << maximum << std::endl; } 

      The output of this program is the following

       maximum = 2147483647 maximum = -2147483648 

      As can be seen from the output, if we use the standard function std::abs , then the value in absolute value will be 2147483647 . And if you compare the numbers as negative numbers, then the maximum in absolute value will be -2147483648

      For clarity, simply replace the maximum variable type declaration in the program from int to unsigned int

       unsigned int maximum = std::max({ std::numeric_limits<int>::min(), std::numeric_limits<int>::max() }, max_abs1); 

      And you for the program will get the following result

       maximum = 2147483647 maximum = 2147483648 

      It can be seen from the output that the first value obtained after applying the standard function std::abs gives an incorrect result.

      For floating-point numbers, it suffices to use the standard function std::abs .

      When a sequence of numbers is not specified using the std::initializer_list object, the std::max_element algorithm can be used. For example,

       #include <iostream> #include <iomanip> #include <algorithm> #include <iterator> #include <cstdlib> #include <limits> int main() { int a[] = { std::numeric_limits<int>::min(), std::numeric_limits<int>::max() }; auto max_abs = [](int x, int y) { return (y < 0 ? y : -y) < (x < 0 ? x : -x); }; int *maximum = std::max_element(std::begin( a ), std::end( a ), max_abs); std::cout << "maximum = " << ( unsigned int )*maximum << std::endl; } 

      The output of the program to the console will be, as expected, the following

       maximum = 2147483648 
      • It is not clear. In the question they ask how to find the module maximum in modulus, but if you find it -2147483648, then its module will not fit in the int - well, what you are writing about. But then at least all portability is lost? So the question in general is simply meaninglessly strong? \ - Mikhailo
      • @Mikhailo I think the question is just clumsily formulated. Most likely it is necessary to find an element in the sequence, the absolute value of which is maximum. I showed how to do it. If you want to output the result as a non-negative number, then you need to convert it to an unsigned type. - Vlad from Moscow