检查数字是否有相同的符号

时间:2009-08-16 18:13:03

标签: c++

我遇到了这个: Simplest way to check if two integers have same sign?

如何将其扩展为两个以上的数字(不一定是整数)?比如说,检查4个数字是否具有相同的符号(+ ve或-ve)。

我不想尽可能使用位操作......只是逻辑条件。

感谢。

6 个答案:

答案 0 :(得分:6)

我们假设数字被传递到vector<int>

遍历数组,检查两个后续数字是否具有相同的符号,如果不是第一个非等号符号则返回false。

答案 1 :(得分:2)

这样的东西?

if ( n1 > 0 && n2 > 0 ... && nN > 0 )
  // all positives
else if ( n1 < 0 && n2 < 0 ... && nN < 0 )
  // all negatives
else
  // mixed signs

由于short-circuit evaluation,它会很快。

答案 2 :(得分:2)

除非我误解了这个问题,否则以下人员应该为数字向量做好工作:

#include <iostream>
#include <vector>
using namespace std;

template <typename T> int Sign( T t ) {
    return t < 0 ? -1 : 1;
}

template <typename T> bool SameSign( std::vector <T> & v ) {
    if ( v.size() == 0 )  {
        throw "invalid size";
    }
    int sign = Sign( v[0] );
    for ( int i = 1; i < v.size(); i++ ) {
        if ( Sign( v[i]) != sign ) {
            return false;
        }
    }
    return true;
}


int main() {
    std::vector <int> v;
    v.push_back(1);
    v.push_back(1);
    v.push_back(-1);
    bool same = SameSign( v );
    std::cout << (same ? "same" : "not same") <<"\n";
}

答案 3 :(得分:2)

这是一个通用的实现。这将检查容器的元素是否都共享相同的属性。

一个版本将迭代器返回给第一个不匹配的元素,简洁版本只返回true或false。

因为它是通用的,你也可以检查它们是否都是偶数,例如:

// shared_property.hpp
#ifndef SHARED_PROPERTY_HPP
#define SHARED_PROPERTY_HPP

// checks if all elements share a single property
// if one element does not share a property,
// it returns an iterator to that element
template <typename Iter, typename Func>
Iter share_property(Iter first, Iter last, Func func)
{
    for(; first != last; ++first)
    {
        if (!func(*first))
        {
            // differs
            break;
        }
    }

    return first;
}

// only indicates if all elements share a property
template <typename Iter, typename Func>
bool share_property_concise(Iter first, Iter last, Func func)
{
    return share_property(first, last, func) == last;
}

#endif

示例程序:

#include "shared_property.hpp"

#include <functional>
#include <iostream>
#include <vector>

typedef std::vector<int> container;

void negative_test(void)
{
    container negatives;
    negatives.push_back(-1);
    negatives.push_back(-2);
    negatives.push_back(-3);

    if (share_property_concise(negatives.begin(), negatives.end(),
        std::bind2nd(std::less<int>(), 0)))
    {
        std::cout << "All elements are less than 0." << std::endl;
    }
    else
    {
        std::cout << "Not all elements are less than 0." << std::endl;
    }
}

bool is_even(int i)
{
    return i % 2 == 0;
}

void even_test(void)
{
    container evens;
    evens.push_back(2);
    evens.push_back(4);
    evens.push_back(10);

    if (share_property_concise(evens.begin(), evens.end(),
        is_even))
    {
        std::cout << "All elements are even." << std::endl;
    }
    else
    {
        std::cout << "Not all elements are even." << std::endl;
    }
}


int main(void)
{
    negative_test();    
    even_test();
}

它也适用于根据属性过滤容器:

#include "shared_property.hpp"

#include <algorithm>
#include <cstdlib>
#include <ctime>
#include <functional>
#include <iostream>
#include <iterator>
#include <vector>

typedef std::vector<int> container;

template <typename Iter, typename OutIter, typename Func>
Func filter_container(Iter first, Iter last, OutIter out, Func func)
{
    first = share_property(first, last, func);
    while (first != last)
    {
        *out++ = *first++;

        first = share_property(first, last, func);
    }

    return func;
};

int make_number(void)
{
    return std::rand() % 20 - 10;
}

void find_negatives(void)
{
    container numbers;
    std::generate_n(std::back_inserter(numbers), 20, make_number);

    container negatives;
    filter_container(numbers.begin(), numbers.end(), std::back_inserter(negatives),
        std::bind2nd(std::greater<int>(), 0));

    std::cout << "List: " << std::endl;
    std::copy(numbers.begin(), numbers.end(),
        std::ostream_iterator<int>(std::cout, "\n"));
    std::cout << std::endl;

    std::cout << "Negatives:" << std::endl;
    std::copy(negatives.begin(), negatives.end(),
        std::ostream_iterator<int>(std::cout, "\n"));
}

int main(void)
{
    std::srand(static_cast<unsigned>(std::time(0)));

    find_negatives();   
}

一致性

此算法将测试一组的一致性:

// consistent_property.hpp
#ifndef CONSISTENT_PROPERTY_HPP
#define CONSISTENT_PROPERTY_HPP

#include <boost/logic/tribool.hpp>

// checks if all elements consistently pass/fail a property
// if it returns indeterminate, then the results are mixed,
// otherwise all results pass or failed as indicated
template <typename Iter, typename Func>
boost::logic::tribool consistent_property(Iter first, Iter last, Func func)
{
    bool result = func(*first++);

    for(; first != last; ++first)
    {
        if (func(*first) != result)
        {
            // differs
            return boost::logic::indeterminate;
        }
    }

    return result;
}

#endif

这将检查一个容器中的属性是否一致,而不是它是否成立。也就是说,如果所有元素都没有通过属性,它将返回false,如果它们都执行,则返回true(与share_property_concise相同的结果),如果结果混合则不确定。

以下是一个例子:

#include "consistent_property.hpp"

#include <algorithm>
#include <functional>
#include <iostream>
#include <vector>

typedef std::vector<int> container;

void check_sign(void)
{
    container positives;
    positives.push_back(1);
    positives.push_back(2);
    positives.push_back(3);

    boost::logic::tribool result =
        consistent_property(positives.begin(), positives.end(),
        std::bind2nd(std::greater<int>(), 0));

    if (boost::logic::indeterminate(result))
    {
        std::cout << "Mixed signs." << std::endl;
    }
    else if (result)
    {
        std::cout << "All positive." << std::endl;
    }
    else
    {
        std::cout << "All negative." << std::endl;
    }
}

int main(void)
{
    check_sign();
}

最后,我提供了一个仿函数,可以获得不太具体的一致性结果。虽然上面将告诉一致性是否失败,传递或混合,但使用带有share_property的仿函数只能确定集合是否一致或混合。你不能推断它是一致的。

这可能是解决原始问题的最简单方法。要有一个相同的标志,而不需要知道那个标志是什么,可以通过这种方式完成,给出一个快速的&amp;结果简单;或者它们都是相同的标志。

将以下内容添加到consistent_property.hpp

// the functor to determine if the property that all elements
// in a set share, is the property that they all pass or fail
// a secondary property. there is no way to deduce what the
// status was (if they all passed or all failed), only if
// all the elements were consistent. true indicates consistency,
// false indicates lack thereof
template <typename T, typename Func>
class consistent_shared_property_binder
{
public:
    consistent_shared_property_binder(const Func& func) :
    _func(func)
    {
    }

    bool operator()(const T& t)
    {
        bool result = _func(t);

        static bool status = result; // only initialized first run

        return status == result;
    }

private:
    Func _func;
};

// bind a function to the functor
template <typename T, typename Func>
consistent_shared_property_binder<T, Func> consistent_property(Func func)
{
    return consistent_shared_property_binder<T, Func>(func);
}

示例程序:

#include "consistent_property.hpp"
#include "shared_property.hpp"

#include <algorithm>
#include <functional>
#include <iostream>
#include <vector>

typedef std::vector<int> container;

bool is_positive(int i)
{
    return i > 0; 
}

void check_sign_anonymous(void)
{
    container positives;
    positives.push_back(-1);
    positives.push_back(-2);
    positives.push_back(-3);

    if (share_property_concise(positives.begin(), positives.end(),
        consistent_property<int>(is_positive)))
    {
        std::cout << "All the same sign." << std::endl;
    }
    else
    {
        std::cout << "Mixed signs." << std::endl;
    }
}

int main(void)
{
    check_sign_anonymous();
}

我想我已经完成了。 :P

(注意:如果有人看到更好的方法做某事,或者有错误,请告诉我!)

答案 4 :(得分:1)

signof()将返回-1表示任何负数,0表示0表示,1表示任何正数。

编辑:

如果signof()signbit()不存在,您可以尝试使用按位运算来确定。对于负32位整数,(number >> 31)将返回1

答案 5 :(得分:1)

以下是多个值的示例。您只需要从两值情况中创建相同符号比较的连通图:

(a<0) == (b<0) && (b<0) == (c<0) && (c<0) == (d<0) && ...

通过连接,我的意思是用“b”检查“a”,然后用“c”检查“b”等。