2013-05-21 2 views
0

У меня есть небольшая проблема при назначении результата переменной, это происходит в первый раз для меня сейчас. Я называю Convert() с «AAA» в качестве параметра, вот мой результат:Число, меняющее значение при присвоении переменной?

aaa 

**676** *(value from cout)* = 26^(3-1)*1  **675** *(value of the variable)* 

+26 = 26^(3-2)*1 700 

+1 = 26^(3-3)*1 701 

701 

А вот код:

string alphabet="abcdefghijklmnopqrstuvwxyz"; 

unsigned long long Convert(string &str){ 
    unsigned long long wvalue=0; 
    for(int i=0;i<str.size();++i){ 
    size_t found=alphabet.find(str[i]); 
    if(found==string::npos) 
     cout<<"Please enter only lowercase letters of the english alphabet!"<<endl; 

    unsigned long long add=((found+1)*pow(26,(str.size()-(i+1)))); 
    wvalue+=add; 
    if(i>0)cout<<"+"; 
    cout<<"\t"<<((found+1)*pow(26,(str.size()-(i+1))))<<" = "<<"26^("<<str.size()<<"-"<<(i+1) <<")*"<<(found+1)<<"\t"<<wvalue<<endl; 
    } 
    return wvalue; 
} 

Скорее всего, я что-то очень очевидное не хватает, но я не могу выясните это.

((found+1)*pow(26,(str.size()-(i+1)))) 

делает расчет, и это делает, как предполагается, в результате в соиЬ-даного правильно. Но переменная вычитается 1 в первых двух присваиваниях.

ответ

2

pow - функция с плавающей запятой. Он принимает и возвращает числа с плавающей запятой. Присвоение числа с плавающей запятой целочисленной переменной усекает его до целочисленного числа, поэтому оно могло быть 675.9999999 непосредственно перед присвоением, которое будет присвоено 675 при назначении целочисленной переменной add.

cout также округляет числа с плавающей запятой, в зависимости от конфигурации, например, до 6 значащих цифр. 676.0 - лучшее приближение, чем 675.999, поэтому вы видите 676 на выходе.

Поскольку вы не хотите рассчитывать с реальными числами, но только с целыми числами, вам лучше оставаться со встроенными функциями. Чтобы взять 26 на мощность n, лучше использовать умножение n раз. Так как вы уже используете цикл, и хотели бы иметь следующую мощность 26 для каждого персонажа, лучше всего добавить переменную, в которой вы сохраняете текущее значение мощности, например:

unsigned long long currentFactor = 1; 
for (...) { 
    ... 
    unsigned long long add = currentFactor * (found+1); 
    wvalue += add; 
    currentFactor *= 26; 
} 

Также обратите внимание, что вы не нужно находить символ в строке алфавита. Вы также можете просто использовать арифметику символов для этого:

int charNumber(char c) { 
    if (c >= 'a' && c <= 'z') 
     return c - 'a'; // calculate the position of c relative to 'a' 
    else 
     return -1;  // error 
} 
+0

Спасибо за ответ. Я все еще не понимаю, почему 26^2 усекается до 25 при преобразовании из double в int, но по крайней мере я знаю, что это значит и может действовать соответствующим образом. –

+0

Я только заметил, что вы хотите иметь самый правый (последний) символ, чтобы иметь наименьшее значение в вашей сумме. Чтобы добиться этого с помощью метода «умножить в каждом шаге», вам нужно итератировать в обратном направлении по строке. Я предлагаю использовать итераторы для этого. Чтобы итератировать в обратном направлении, просто используйте 'string.rbegin()' и 'string.rend()' и увеличивайте итератор на каждом шаге. Пример можно найти здесь (http://www.cplusplus.com/reference/string/string/rend/). – leemes

+0

Для ошибок округления с плавающей точкой [прочитайте эту очень информативную статью] (http://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html#680). Я знаю, что это долго, вам не обязательно все это читать, но особенно раздел об ошибках округления объясняет, что происходит в вашем коде. – leemes

Смежные вопросы