当我尝试将双精度数作为元素分解为数组时,为什么我会得到一个偏移量阻止我获取最后一位数字?

When I try to decompose a double number into an array as elements, why do I get an offset preventing me from getting the last digit?

我有问题。 我想从给定的数字中获取每个数字作为同一数组中的一个元素

但是当我编译时,如果我将一次迭代的范围扩展到给定数字的大小以上,我会在调试模式下从 Visual Studio 得到一个损坏的数据异常作为异常。

我首先想到的是因为 int 类型作为 4 字节实体的最大长度只有 4 位数字,因为我过去只得到一位数字来表示大于 9999 的数字。但我注意到我的数字从迭代值开始一个太晚了...这使得无法显示最后一位数字。

如果我给给定的数字加一个零,我可以在相反的方向手动偏移,但这对我的原始数字不起作用。

但是,我找不到解决方法...这是我的代码。 在寻求帮助之前,这里有一个屏幕截图解释了用于将数字转换为数组的原理:math theory formula 我只想用数字类型解决它,因为 char 类型涉及另一种使用缓冲区管理内存的方式......我真的不知道如何处理。

有人可以帮我完成调试吗?

#include <iostream>
#include <math.h>

//method to convert user number entry to array of digits
long long numToArray(double num,double arrDigits[], const long long n) {
    //instanciate variables

        //array of with m elements
    arrDigits[n];
    double* loopValue = new double(0);

    //extract the digits and store them into arrDigits array
    for (long long i = 0; i < n; i++) {
        long temp = 0;
        for (long k = 0; k < i + 1; k++) {
            //mathematical general formula
            temp += arrDigits[i - k] * pow(10, k);
            loopValue = new double(0);
            *loopValue = floor(num / pow(10, n - i)) - temp;
            arrDigits[i] = *loopValue;
        }
        std::cout << "digits array value at " << i << " is " << arrDigits[i] << " \n";
    }
    return 0;
}
//main program interacting with the user
int main()
{
    std::cout << "please type an integer: ";
    double num;
    const long long n = sizeof(num);
    double array[n]{};
    std::cin >> num;
    //call the method to test if all values are in the array
    numToArray(num, array, n);
    return 0;
}

Explaining the troubleshoot

注意:如果我从 n 扩展到 n+1,Visual Studio 会显示错误。如果我让类型为 int 或 long,则 sizeof(num) 始终为 4 ... 然后,我必须将它设置为 double 并从主作用域中提取它,这使得它 ...double... 人们要求删除指针,如果我这样做,运行 程序是不可能的。

I want from a given number to get each digit as an element in the same array.

如果想简单的把每个数放到一个数组中,只需要几行代码就可以把小数转换成字符串,去掉小数点(如果有的话),然后把字符串复制到一个缓冲区:

#include <iostream>
#include <vector>
#include <string>
#include <sstream>
#include <algorithm>
#include <iterator>
#include <iomanip>

int main() 
{
    double d = 1.45624234;
    
    std::ostringstream strm;
    strm << std::setprecision(12);

    // copy this to a string using the output stream
    strm << d;
    std::string s = strm.str();

    // remove the decimal point
    s.erase(std::remove(s.begin(), s.end(), '.'), s.end());

    // Now copy each digit to a buffer (in this case, vector)
    std::vector<int> v;
    std::transform(s.begin(), s.end(), std::back_inserter(v), [&](char ch) { return ch - '0';});

    // output the results
    for (auto c : v )
      std::cout << c;
}

输出:

145624234

标准库已经为您完成了您所做的所有工作。在这种情况下,当流式传输到缓冲区时,double 的重载 operator << 会创建字符串。它是怎么做到的?这基本上就是您的代码试图做的事情,但显然是安全和正确的。

然后只需将每个数字字符转换为表示该数字的实际整数,这就是 std::transform 所做的。通过从每个 char 数字中减去字符 0,将每个数字字符复制到向量中。

#include <iostream>
#include <math.h>
#include <list>

int main()
{
    //Entry request of any natural integer within the range of double type
        std::cout << "Please type a natural integer from 1 to 99999999\n";
        double num;
        std::cin >> num;

        //counting the number of digits
        int count = 0;
        long long CountingNum = static_cast<long long>(num);
        while (CountingNum != 0) {
            CountingNum = CountingNum/10;
            ++count;
        }
        std::cout << "number of digits compositing your natural integer: " << count<<std::endl;

        //process the value for conversion to list of digits, so you can
        //access each digits by power and enhance your calculus operations
        double converternum = num * 10;//removing the right offset to keep the last digit
        const int containerSize = sizeof(double); //defining array constant size
        int sizeRescale = containerSize - count;//set general offset to handle according to the user entry
        double arrDigits[containerSize] = {};//initialize array with a sufficient size.
        double* loopValue = new double(0); //define pointer variable to make to operation possible

        //extract the digits and store them into arrDigits array
        for (long long i = 0; i < containerSize; i++) {
            long temp = 0;
            for (long k = 0; k < i + 1; k++) {
                //mathematical general formula adapted to the computation
                temp += arrDigits[i - k] * pow(10, k);
                loopValue = new double(0); //reinitialize the pointer
                *loopValue = floor(converternum / pow(10, containerSize - i)) - temp; //assign the math formula to the pointer
                arrDigits[i] = *loopValue;//assigne the formula for any i to the array relatively to k
            }
            std::cout << "digits array value at " << i << " is " << arrDigits[i] << " \n";
        }
        //convert array to a list
        std::list<double> listDigits(std::begin(arrDigits), std::end(arrDigits));
        //print the converted list
        std::cout << "array converted to list: ";
        for (double j : listDigits) {
            std::cout << j << " ";
        }
        std::cout << std::endl;
        //remove the zeros offset and resize the new converted list
        for (int j = 0; j < sizeRescale; j++) {
            listDigits.pop_front();
        }
        std::cout << "removed zero element to the list\n";
        for (double i : listDigits) {
            std::cout << i << " ";
        }
        std::cout << "natural integer successfully converted into list digits data\n";
        return 0;
}

an example on debug mode in Visual Studio 2019

最后我把整个代码封装成了两个函数。但是我在第一次和最后一次迭代中有额外的价值...

答案基本完成,只需要解决从main内部移动到它拥有的函数的偏移量。我终于从两个新函数中添加了一个新的数组变量,它具有我想要的确切大小,所以我们得到了可以在很远的地方操作的数组。

#include <iostream>
#include <math.h>
#include <list>

int CountNumberDigits(int num) {
    int count = 0;
    long long CountingNum = static_cast<long long>(num);
    while (CountingNum != 0) {
        CountingNum = CountingNum / 10;
        ++count;
    }
    return count;
}

double* NumToArray(double num) {
    double converternum = num * 10;//removing the right offset to keep the last digit
    const int containerSize = sizeof(double); //defining array constant size
    int sizeRescale = containerSize - CountNumberDigits(num);//set general offset to handle according to the user entry
    double arrDigits[containerSize] = {};//initialize array with a sufficient size.
    double* loopValue = new double(0); //define pointer variable to make to operation possible

    //extract the digits and store them into arrDigits array
    for (long long i = 0; i < containerSize; i++) {
        long temp = 0;
        for (long k = 0; k < i + 1; k++) {
            //mathematical general formula adapted to the computation
            temp += arrDigits[i - k] * pow(10, k);
            loopValue = new double(0); //reinitialize the pointer
            *loopValue = floor(converternum / pow(10, containerSize - i)) - temp; //assign the math formula to the pointer
            arrDigits[i] = *loopValue;//assigne the formula for any i to the array relatively to k
        }
    }

    //convert array to a list
    std::list<double> listDigits(std::begin(arrDigits), std::end(arrDigits));
    for (double j : listDigits) {
        std::cout << j << " ";
    }

    //remove the zeros offset and resize the new converted list
    for (int j = 0; j < sizeRescale; j++) {
        listDigits.pop_front();
    }
    //convert list to array
    double* arrOutput = new double[listDigits.size()]{};
    std::copy(listDigits.begin(), listDigits.end(), arrOutput);
    double* ptrResult = arrOutput;
    return ptrResult;
}

int main()
{
    //Entry request of any natural integer within the range of double type
    std::cout << "Please type a natural integer from 1 to 99999999\n";
    double num;
    std::cin >> num;
    int count = CountNumberDigits(num);
    std::cout << "number of digits compositing your natural integer: " << count << std::endl;

    double* ptrOutput = NumToArray(num);
    //reduce the array to the num size
    double* shrinkArray = new double[CountNumberDigits(num)];
    for (int i = 0; i < CountNumberDigits(num); i++) {
        *(shrinkArray+i) = ptrOutput[i];
        std::cout << *(shrinkArray+i) << " ";
    }