按位数

时间:2017-08-13 14:17:58

标签: c

我有一个print_number函数。

该功能检查是否存在数字前面的' - ',然后它反转该数字并取每个数字并打印出来。算法工作得很好但是如果我给-2.147.483.648(应该是整数的下限)它pritns -0并且我不知道为什么。

#include<stdio.h>

void    print_char(char character)
{
    printf("%c",character);
}

void    print_number(int nr)
{

    int reverse=0;

    if (nr < 0)
    {
        print_char('-');
        nr *= -1;
    }

    while(nr > 9)
    {
        reverse = reverse * 10 + nr % 10;
        nr = nr / 10;
    }
    print_char(nr + '0');

    while(reverse)
    {
        print_char(reverse % 10 + '0');
        reverse = reverse / 10;
    }
}

3 个答案:

答案 0 :(得分:1)

当你做的时候

if (nr < 0)
{
    print_char('-');
    nr *= -1;
}

它将负数反转为正数。 如果你将它运行-2.147.483.648,你将收到

nr = 2.147.483.648 // == binary 1 0000000000000000000000000000000

由于INT在您的架构中是32 BIT变量(并且规格至少有16个BIT变量),因此'1'溢出它等等

nr = 0 // For gcc-like C realisation

接受ISO9899规范,signed int overflow的这种行为是实现指定的东西,可能无法预测共同。

如果您需要将程序用于较大的值,请使用long long值。 类似的东西:

#include<stdio.h>

void    print_char(char character)
{
    printf("%c",character);
}

void    print_number(long long nr)
{
    int reverse=0;

    if (nr < 0)
    {
        print_char('-');
        nr *= -1;
    }

    while(nr > 9)
    {
        reverse = reverse * 10 + nr % 10;
        nr = nr / 10;
    }
    print_char(nr + '0');

    while(reverse)
    {
        print_char(reverse % 10 + '0');
        reverse = reverse / 10;
    }
}

void main(void){
    print_number(-2147483648LL);
}

并测试:

> gcc test.c
> ./a.out 
-2147483648

答案 1 :(得分:1)

首先,INT的MAX和MIN范围分别为-2,147,483,6482,147,483,647
否定-2,147,483,648表示正值2,147,483,648会导致溢出1,因为它超出了MAX范围的范围。 此操作将产生相同的-2,147,483,648

其次,在整数反转过程中可能会遇到溢出 例如,在2147483647的中间结果之后,反转746384741会导致溢出 因此,您应该通过抛出异常或返回0来处理它。

第三,用于反转数字的循环不准确。它应该循环到while(nr != 0)

这是完整的代码。

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>

int main()
{
    void reverseNumber(int);

    reverseNumber(124249732);
    return 0;
}

void reverseNumber(int nr)
{
    printf("nr = %d\n", nr);

    int reverse = 0;
    bool neg = false;
    if (nr < 0) {
        neg = true;
        nr *= -1;
    }

    while (nr != 0) {
        int digit = nr % 10;
        int result = reverse * 10 + digit;

        if ((result - digit) / 10 != reverse) {
            printf("ERROR\n");
            exit(0);
        }

        reverse = result;
        nr = nr / 10;
    }

    if(neg) {
        printf("%c", '-');
    }
    printf("%d\n", reverse);
}

答案 2 :(得分:0)

nr *= -1;nr == INT_MIN的问题,因为它是签名的整数溢出。结果是未定义的行为(UB)。最好避免。

更广泛的整数并不总是可用。

使用OP的一般方法,在nr减少之前不要更改void print_number(int nr) { int reverse = 0; if (nr < 0) { print_char('-'); //nr *= -1; } while (nr/10) { // new test reverse = reverse * 10 + nr % 10; nr = nr / 10; } reverse = abs(reverse); // reverse = |reverse| nr = abs(nr); // nr = |nr| print_char(nr + '0'); while (reverse) { print_char(reverse % 10 + '0'); reverse = reverse / 10; } } 的符号。

class Detector : public QIODevice {
    Q_OBJECT
    Q_DISABLE_COPY(MasterDevice)

public:
    enum CHANNEL_TYPE {
        DataChannel,
        ControlChannel
    };

private:
    QTcpSocket *controlDevice;
    QTcpSocket *dataDevice;

    QHostAddress hostAddress;

    quint16 dataPort;
    quint16 controlPort;

public:
    explicit Detector(QObject *parent, QHostAddress hostAddress, quint16 dataPort, quint16 controlPort)
        : QIODevice(parent)
        , hostAddress(hostAddress)
        , dataPort(dataPort)
        , controlPort(controlPort)
    {
        controlDevice = new QTcpSocket(this);
        connect(controlDevice, SIGNAL(readyRead()),this, SLOT(controlChannelReadReady()));

        dataDevice = new QTcpSocket(this);
        connect(dataDevice, SIGNAL(readyRead()),this, SLOT(dataChannelReadReady()));
    }

    virtual ~Detector() {}

    bool open(OpenMode mode) override {
        QIODevice::open(mode);

        controlDevice->connectToHost(hostAddress, controlPort, QTcpSocket::ReadWrite);
        dataDevice->connectToHost(hostAddress, dataPort, QTcpSocket::ReadOnly);
    }

    qint64 readData(char *data, qint64 maxSize) override {
        QTcpSocket *socket;

        switch ( currentReadChannel() ) {
        case DataChannel:
            socket = dataDevice;
            break;
        case ControlChannel:
            socket = controlDevice;
            break;
        default:
            return -1;
            break;
        }

        return socket->read(data, maxSize);
    }

    qint64 writeData(const char * data, qint64 maxSize) override {
        QTcpSocket *socket;

        switch ( currentWriteChannel() ) {
        case DataChannel:
            socket = dataDevice;
            break;
        case ControlChannel:
            socket = controlDevice;
            break;
        default:
            return -1;
            break;
        }

        return socket->write(data, maxSize);
    }

private slots:
    void controlChannelReadReady() {
        emit channelReadyRead(ControlChannel);
    }

    void dataChannelReadReady() {
        emit channelReadyRead(DataChannel);
    }
};