String đột nhiên thay đổi giá trị

Em đang tìm số fibo nhỏ nhất >= tmp, với F, tmp đều là std::string
Hàm lessThan trả về true nếu F[i] < tmp
Hàm add() để cộng 2 string lại (tất nhiên là string chứa các chữ số)

            while(lessThan(F[i], tmp))
            {
                ++i;
                F[i] = add(F[i - 1], F[i - 2]);
                //std::cout << F[i] << '\n' << tmp << '\n';
            }

Khi em để tmp là 1 số lớn (1000 chữ số 9) thì em tính F. Mọi chuyện vẫn ổn cho tới bước lặp cuối cùng, F[i] tính ra được là 24314… (ví dụ vậy), còn tmp đang mang giá trị 1000 chữ số 9 thì bỗng nhiên đổi thành 24314…

Mọi người cho em hỏi là tại sao lại vậy ?

Bởi vì giá trị của kiểu Int nó ko lớn đến 1000 chữ số 9 đâu bạn.

Dạ, em để biến tmp là std::string anh ơi

Nhưng bạn phải xem cả hàm lessThan kia nữa. Biết đâu trong đó bạn convert tmp thành int. Vì nếu không thì làm sao so sánh less than được giữa 1 integer và 1 string với nhau. :smiley:

Bạn thử xem cái số lúc bạn bị lỗi có phải số này không: 2147483648. Đây là số lớn nhất của kiểu int. :smiley:

Hic, ở đây, chỉ có biến i là int
Còn lại, F, tmp, là std::string hết
Em có nói rõ rồi mà.

Vậy i làm sao chạy qua giới hạn của kiểu Int được bạn?

Số Fibo có 1000 chữ số là cỡ số thứ 4900, nghĩa là i chỉ chạy tới 4900 thôi ^^

  1. A ko hiểu vì sao e lại dùng while(lessThan(abc < xyz)) trong khi xyz là 1 số cực lớn mà ko số nào lớn hơn được. Vì sao ko thay bằng while(true)?
  2. Để so sánh lessThan thì chắc chắn ko thể so sánh 2 string được mà bắt buộc phải convert nó từ string ra 1 loại number nào đó. Khả năng rất cao trong TH này là kiểu Int. E cần check lại đi.
  3. Trong vòng lặp của e không có điều kiện break do số tmp là số cực lớn mà F[i] ko thể lớn hơn được thì i chạy quá giới hạn Int là chuyện bình thường mà.

Dạ, nói ngắn gọn thì đây là xử lý số lớn nha anh ^^
Anh có thể google ^^

Haha, vậy chúc e tìm lỗi thành công. :v:

Em cần chắc chắn các hàm này làm đúng nhiệm vụ của nó. Do ko xem đc hàm lessthan và hàm cộng nên anh ko kiểm tra đc, em post lên đc ko?
Hàm lessthan có truyền tham chiếu tmp ko? Vì chỉ có hàm này mới thay đổi đc tmp nên kiểm tra lại xem. Còn mà nó là truyền giá trị mà tmp vẫn bị thay đổi thì bí ẩn quá

1 Like

Đây là toàn bộ chương trình của e.
Đề: nhập Q là số truy vấn. Với mỗi truy vấn, nhập một số tối đa 1000 chữ số và kiểm tra xem đó có phải là số Fibo hay không.

#include <iostream>
#include <string>
#define maxN 5000
std::string F[maxN], tmp, gg;
int m;

int toNum(char c) { return c - '0'; }
char toChar(int n) { return n + '0'; }
std::string add(std::string a, std::string b)
{
    int carry = 0, tmp;
    while(a.length() < b.length()) a = '0' + a;
    while(a.length() > b.length()) b = '0' + b;

    for(int i = a.length() - 1; i >= 0; i--)
    {
        tmp = toNum(a[i]) + toNum(b[i]) + carry;
        a[i] = toChar(tmp % 10);
        carry = tmp / 10;
    }

    if(carry > 0) a = toChar(carry) + a;
    return a;
}
bool lessThan(std::string a, std::string b)
{
    if(a.length() < b.length()) return true;
    return a < b;
}

int main()
{
    F[1] = "1"; F[2] = "1";
    std::cin >> m;
    int i = 2;

    while(m--)
    {
        std::cin >> tmp;

        if(lessThan(F[i], tmp))
        {

            while(lessThan(F[i], tmp))
            {
                ++i;
                F[i] = add(F[i - 1], F[i - 2]);
                //std::cout << F[i] << '\n' << tmp << '\n';
            }
        }
        else
        {
            for(int j = 2; j <= i; j++)
                if(F[j] == tmp)
                    { i = j; break; }
        }
        if(F[i] == tmp)
            std::cout << "YES\n";
        else
            std::cout << "NO\n";
    }

    return 0;
}

Em đưa toàn bộ code lên xem :smile:

while(carry){ a+=toChar(carry%10); carry/=10);}

không nên dùng phép cộng của string nhiều như thế. Tốt nhất là push_back vào sau rồi đảo ngược lại

1 Like

Nhưng em vẫn không hiểu sao, các lần lặp trước đều đúng hết, nhưng chỉ tới bước lặp cuối cùng thì tmp lại chuyển luôn :’(

@ltd Nó liên quan gì đến vùng nhớ này nọ không anh :frowning:

Đây là giá trị debug
Cái số 999… là giá trị của tmp, số rối rắm kia là số fib.
Và thấy rằng, đến bước lặp cuối, từ 999…, tmp đã chuyển sang giống fib[i] hoàn toàn :’(

Mình copy, thử build và chạy thử chương trình của bạn thì không thấy lỗi gì:

D:\exam>a
2
1
YES
34
YES

Mình dùng g++:

D:\exam>g++ --version
g++ (x86_64-posix-sjlj, built by strawberryperl.com project) 4.9.2
Copyright (C) 2014 Free Software Foundation, Inc.

Thay hàm lessthan. Hàm cũ chạy mãi mà nó không chịu dừng :cry:

bool lessThan(std::string a, std::string b)
{
	
	if (a.length() < b.length()) return true;
	if (a.length() == b.length()) return (a<b);
	return false;
}

Anh thử với input 1040 số 9. :triumph:

1 Like

Cám ơn mấy anh :heart: em sửa theo anh @rok_Hoang thì chạy được rồi.
Mà nếu được, mấy anh có thể giải thích tại sao cái chương trình ban đầu biến tmp bị đổi giá trị không ?

83% thành viên diễn đàn không hỏi bài tập, còn bạn thì sao?