忽略 std::min 中的零并计算其他数字的最小值
Posted
技术标签:
【中文标题】忽略 std::min 中的零并计算其他数字的最小值【英文标题】:Ignore zero in std::min and calculate minimum of other numbers 【发布时间】:2021-11-07 16:18:13 【问题描述】:非零数的最小值:
#include <iostream>
#include <algorithm>
int main()
double s1 = 1000;
double s2 = 400;
double s3 = 300;
double s4 = 10;
double minimum = std::min(s1, s2, s3, s4);
std::cout<<minimum<<"\n";
double var = 1/minimum;
std::cout<<var;
这工作正常并返回:
10
0.1
问题是当其中一个数字为零时:
#include <iostream>
#include <algorithm>
int main()
double s1 = 1000;
double s2 = 400;
double s3 = 300;
double s4 = 0;
double minimum = std::min(s1, s2, s3, s4);
std::cout<<minimum<<"\n";
double var = 1/minimum;
std::cout<<var;
返回:
0
inf
预期结果:
300
0.00333333
如何在计算中忽略零?
【问题讨论】:
std::min
函数按预期工作,它返回最小值。如果您想忽略零,则需要将其从传递给std::min
的值列表中删除。一种简单的方法是将值放入容器中,使用 std::remove_if
删除零,然后使用例如std::min_element
在容器上。
你可以传递一个 lambda 作为第二个参数来比较运算符并忽略你想忽略的数字。
【参考方案1】:
或者像这样
#include <algorithm>
#include <limits>
#include <vector>
template<std::size_t N>
constexpr double min_no_zero(const double (&values)[N])
static_assert(N>0,"There must be at least one number");
double min = std::numeric_limits<double>::max();
for (const auto value : values)
if ( value != 0.0 )
min = std::min(min, value);
return min;
int main()
constexpr double s1 = 1000.0;
constexpr double s2 = 400.0;
constexpr double s3 = 0.0;
constexpr double s4 = 10.0;
static_assert( min_no_zero( s1, s2, s3, s4 ) == 10.0);
【讨论】:
如果所有值都为零或N
为零,则返回std::numeric_limits<double>::max()
。
@G.Sliepen 好点,但唯一的要求是它不应该返回 0.0。不过,我将添加对 0 元素的检查;)也许要求应该是用 std::numeric_limitsstd::min
工作正常,如果您有特殊要求,您可以传递具有以下签名的比较函数:
bool cmp(const Type1 &a, const Type2 &b);
作为第二个std::min
函数参数(Compare
模板参数):
#include <iostream>
#include <algorithm>
int main()
double s1 = 1000;
double s2 = 400;
double s3 = 300;
double s4 = 0;
auto const ignore_zero = [](auto const& a, auto const& b) -> bool
if(0 == a)
return false;
else if(0 == b)
return true;
return a < b;
;
double minimum = std::min(s1, s2, s3, s4, ignore_zero);
std::cout << minimum << "\n";
但是很奇怪,如果你对你的代码有这样的特殊要求,我建议你:
-
尝试重新设计您的程序。
使用函数/函子助手:
#include <algorithm>
#include <iostream>
#include <vector>
namespace core::helper
template<typename T>
struct special_find final
std::vector<T> nums;
explicit special_find(std::initializer_list<T> nums_)
: nums(std::move(nums_))
auto min() const
return *std::min_element(nums.cbegin(), nums.cend());
special_find& ignore(T const& value)
nums.erase(std::remove_if(nums.begin(), nums.end(), [&value](auto const & item)
return item == value;
), nums.end());
return *this;
;
// namespace core::helper
int main()
double s1 = 1000;
double s2 = 400;
double s3 = 300;
double s4 = 0;
auto const min = core::helper::special_find(s1, s2, s3, s4).ignore(0).min();
std::cout << min << "\n";
【讨论】:
您的ignore_zero
lambda 不满足Compare 的要求,我认为这会导致行为未定义。我运行了一个测试,在其中复制了您的代码,然后交换了s1
和s4
的初始化(所以s1
是0,而s4
是1000),编译并得到0
作为结果。问题是!ignore_zero(a,b) && !(ignore_zero(b,a)
没有建立等价关系。更具体地说,只要 a
不为零,ignore_zero(a,0)
的计算结果就应该为 true
。
另一个问题是,如果所有参数都为零,这仍然可以返回零。【参考方案3】:
确保不要将 0 传递给 min。我想这是不知道您的输入是什么样子的唯一通用答案。
【讨论】:
以上是关于忽略 std::min 中的零并计算其他数字的最小值的主要内容,如果未能解决你的问题,请参考以下文章