当我尝试将双精度数分解为元素数组时,为什么会出现偏移量,从而无法获取最后一位数字?

问题描述

output bug on iteration starting order

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

但是,当我进行编译时,如果将范围从给定数字的大小之上的一次迭代扩展,则我将从Visual Studio的Debug模式中获取损坏的数据异常作为异常。

我首先想到的是因为int类型作为4字节实体的最大长度只有4位,因为我过去只为9999以上的大数获得一位。但是我注意到我的数字也从一个迭代值开始迟了...这使得不可能显示最后一位数字。

如果在给定的数字后加零,则可以手动向相反方向偏移,但这不适用于我的原始数字。

但是,我无法找到解决方法……这是我的代码。 在寻求帮助之前,以下是屏幕截图,解释了用于将数字转换为数组的原理:AvroCoder 我只想用数字类型来解决它,因为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;
}

math theory formula

注意:如果我从n扩展到n + 1,Visual Studio显示错误。如果我将类型设为int或long,则sizeof(num)一直都是4 ... 然后,我必须将其设置为double并从主作用域中将其提取出来,从而使其... double ... 人们要求删除指针,否则我将无法运行该程序。

解决方法

我希望从给定的数字中获取每个数字作为同一数组中的元素。

如果要将每个数字简单地放入数组中,只需几行代码即可将小数转换为字符串,删除小数点(如果存在),然后将字符串复制到缓冲区:

#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(),std::back_inserter(v),[&](char ch) { return ch - '0';});

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

输出:

145624234

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

然后,只需将每个数字字符转换为代表该数字的实际整数,std::transform便会这样做。通过从每个字符数减去字符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) << " ";
    }