Форум программистов, компьютерный форум, киберфорум
Наши страницы

С++ для начинающих

Войти
Регистрация
Восстановить пароль
 
 
Рейтинг: Рейтинг темы: голосов - 11, средняя оценка - 4.64
G@leON
6 / 6 / 1
Регистрация: 02.06.2009
Сообщений: 99
#1

Ошибка преобразования типа - C++

10.05.2012, 01:35. Просмотров 1461. Ответов 32
Метки нет (Все метки)

Задача состояла в следующем: реализация алгоритма проверки n на простоту, используя малую теорему Ферма. В силу недостаточного опыта и позднего времени накумекал следующий код с пояснениями:

В качестве 1 из параметров, передаваемых функциям, выступает маркер простоты.
Это параметр-ссылка на переменную логического типа.
Значение маркера = true после выполнения подтверждает простоту проверяемого числа.

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
int gcd(int v_1, int v_2){
    while (v_2){
        int temp = v_2;
        v_2 = v_1 % v_2;
        v_1 = temp;
    }
    return v_1;
}
 
void ferma_lt_test(bool &prime_marker, int n){
    prime_marker = true;
    if (n<1){
        prime_marker = false;
        cout << "n is not natural" << endl;
    }
    if (n>2) {
        int v_1 = 2;
        while ((gcd(n,v_1)) != 1)
            v_1++;
        double deg_v = n, base_v = v_1;
        long l_v1 = exp(deg_v * log(base_v)), l_v2 = exp((deg_v - 1) * log(base_v));
        l_v1 %= n;
        l_v2 %= n;
        if ((l_v1 != v_1) || (l_v2 != 1))
            prime_marker = false;
    }
}
Здесь ф-ция gcd(v_1,v_2) - нахождение НОД. Вторая функция: Тест малой теоремой Ферма.

Ошибка заключается собственно в том, что при преобразовании double в long в строке:
C++ (Qt)
1
long l_v1 = exp(deg_v * log(base_v)), l_v2 = exp((deg_v - 1) * log(base_v));
Оба значение типа long на 1 меньше, чем возвращаемые функциями значения типа double. Притом, данная ошибка вылезает для чисел до 19 включительно. Число 23, как ни странно, проверяется. Помогите исправить.

Соответственно, число 31 уже выходит за границу допустимого диапазона. Было бы неплохо, так же, услышать подсказку по увеличению допустимого диапазона (например, имеется ли стандартный модуль(заголовок) длинной математики в C++, а если нет, то какой лучше и где найти...).

Добавлено через 52 минуты
После проверки на различные варианты преобразования выяснил, что они не помогают, ни преобразование в стиле C, не преобразование в стиле С++ (cast которые). Конечно, проблему можно разрешить проверкой на принадлежность к определенному числу (типа if n < 19 ... то прибавлять к функции +1), но это вообще не выход. Так что проблему надо решать альтернативным методом. Каким, не знаю.

Я так понимаю, задача вылазит несколько другим боком. Нужно как то умудрится возвести в степень n и n-1 число v_1, а результат потом делить на n с получением остатка от деления.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
10.05.2012, 01:35
Здравствуйте! Я подобрал для вас темы с ответами на вопрос Ошибка преобразования типа (C++):

Ошибка преобразования типа в классе - C++
Дан класс, который реализует длинную арифметику с положительными\отрицательными целыми числами. Все числа одинаковой длины и их макс....

Ошибка преобразования: значение типа "float *" нельзя присвоить сущности типа "float" - C++
Помогите исправить.Значение типа &quot;float *&quot; нельзя присвоить сущности типа float void Mode2() { const int n=20,m=20 ; float a, b;...

Преобразования массива с типа int к типу char - C++
Помогите решить задачу. Требуется создать шаблон класса для преобразования массива с типа int к типу char, помогите кто чем сможет буду...

Оператор преобразования типа и его эквивалентные замены, поиск строки в текстовом файле , содержащей заданный - C++
Господа, был бы очень признателен если бы кто то помог ответить на вапросы http://cs616225.vk.me/v616225102/122f8/5kAaFEGoDn0.jpg

В массив типа double записываю целые числа (типа int), но ошибка не вылазиет! - C++
Вот программулька: #include &lt;iostream&gt; using namespace std; #include &lt;conio.h&gt; int main() { double arr={1,2,3,4,5}; ...

Ошибка преобразования - C++
Вот мой код. В общем в конце выбивает &quot;error C2664: kasat: невозможно преобразовать параметр 5 из &quot;double (__cdecl *)(double,double)&quot;...

32
Avazart
Эксперт С++
7433 / 5472 / 310
Регистрация: 10.12.2010
Сообщений: 24,397
Записей в блоге: 17
10.05.2012, 05:18 #2
Что такое exp() и где оно живет?
0
G@leON
6 / 6 / 1
Регистрация: 02.06.2009
Сообщений: 99
10.05.2012, 05:32  [ТС] #3
Она из заголовка <math.h>
Давай так. Что бы проще было, вкладываю код юнита, заголовка и собственно main.
0
Вложения
Тип файла: rar Библиотеки проверки на простоту.rar (1.5 Кб, 5 просмотров)
Toshkarik
1147 / 864 / 51
Регистрация: 03.08.2011
Сообщений: 2,404
Завершенные тесты: 1
10.05.2012, 05:48 #4
Avazart, exp()
Это вот эта теорема?
0
Avazart
Эксперт С++
7433 / 5472 / 310
Регистрация: 10.12.2010
Сообщений: 24,397
Записей в блоге: 17
10.05.2012, 06:02 #5
У мня компилится без ошибок...

Добавлено через 7 минут
Toshkarik, Само выражение просто страшное, напомнило чем то шаблоны STL,подумал что exp() самописная а не экспонента (время позднее или точнее раннее)

Добавлено через 1 минуту
C++
1
2
long l_v1 = exp(deg_v * log(base_v));
long l_v2 = exp((deg_v - 1) * log(base_v));
0
G@leON
6 / 6 / 1
Регистрация: 02.06.2009
Сообщений: 99
10.05.2012, 06:07  [ТС] #6
Компилитс без ошибок, я вообщето писал что все ОК.
Ошибка в преобразовании. Преобразование он делает, но теряет 1.

Там где для компиляции я в выходной поток вставил результаты возведения:
void ferma_lt_test(bool &prime_marker, int n){
prime_marker = true;
if (n<1){
prime_marker = false;
cout << "n is not natural" << endl;
}
if (n>2) {
int v_1 = 2;
while ((gcd(n,v_1)) != 1)
v_1++;
double deg_v = n, base_v = v_1;
long l_v1 = exp(deg_v * log(base_v)), l_v2 = exp((deg_v - 1) * log(base_v));
cout << v_1 << " " << (l_v1) << " " << l_v2 << endl; //ЗДЕСЬ
l_v1 %= n;
l_v2 %= n;
if ((l_v1 != v_1) || (l_v2 != 1))
prime_marker = false;
}
}
Сделай вот так:
C++ (Qt)
1
cout << exp(deg_v * log(base_v)) << " " << (l_v1) << " " << l_v2 << endl;
И да, код в модуле уже модифицированный. Надо в модуль вставить код, который выше.
0
Avazart
Эксперт С++
7433 / 5472 / 310
Регистрация: 10.12.2010
Сообщений: 24,397
Записей в блоге: 17
10.05.2012, 06:14 #7
Что значит "1"?

Добавлено через 5 минут
Поидее так должно быть
C++
1
2
long double l_v1 = (exp(deg_v * log(base_v)));
long double l_v2 = (exp((deg_v - 1) * log(base_v)));
если хочишь большую точность
0
Toshkarik
1147 / 864 / 51
Регистрация: 03.08.2011
Сообщений: 2,404
Завершенные тесты: 1
10.05.2012, 06:16 #8
Так Вы уж определитесь, с какими типами работаете, не удивительно, что есть погрешность при преобразовании вещественного типа в целочисленный.
0
G@leON
6 / 6 / 1
Регистрация: 02.06.2009
Сообщений: 99
10.05.2012, 06:19  [ТС] #9
Мне дальше надо делить с получением остатка. Поэтому мне надо получить целочисленное.
Ни 1 из вещественных типов не обрабатывается оператором %.

Единица в смысле в значении. Например 13.
2^13 это 8192, а результат после long l_v1 = exp(deg_v * log(base_v)) равен 8191.

И я понимаю, что это некрасиво. С точки зрения машины все правильно, но я то понимаю, что есть погрешность при преобразовании вещественного типа в целочисленный. Просто тип double не делится с остатком))
0
Toshkarik
1147 / 864 / 51
Регистрация: 03.08.2011
Сообщений: 2,404
Завершенные тесты: 1
10.05.2012, 06:21 #10
Для этого есть функция fmod().
0
Avazart
Эксперт С++
7433 / 5472 / 310
Регистрация: 10.12.2010
Сообщений: 24,397
Записей в блоге: 17
10.05.2012, 06:21 #11
Может человек имеет ввиду округление, а не приведение типов?
0
Toshkarik
1147 / 864 / 51
Регистрация: 03.08.2011
Сообщений: 2,404
Завершенные тесты: 1
10.05.2012, 06:22 #12
А чем при возведении в степень не устроила функция pow()?
0
Avazart
Эксперт С++
7433 / 5472 / 310
Регистрация: 10.12.2010
Сообщений: 24,397
Записей в блоге: 17
10.05.2012, 06:24 #13
Выглядит не так страшно
1
Toshkarik
1147 / 864 / 51
Регистрация: 03.08.2011
Сообщений: 2,404
Завершенные тесты: 1
10.05.2012, 06:27 #14

Не по теме:

Avazart,


G@leON, если хотите сохранить свой код, то попробуйте сделать вот так
C++
1
2
long l_v1 = floor( exp(deg_v * log(base_v)) + .5 ),
     l_v2 = floor( exp((deg_v - 1) * log(base_v)) + .5 );
1
G@leON
6 / 6 / 1
Регистрация: 02.06.2009
Сообщений: 99
10.05.2012, 06:36  [ТС] #15
Во, fmod - то, что нужно.
floor - это тоже хорошо.
А функция pow(), она конечно хороша, просто такая форма возведения мне понятна. А код pow() мне смотреть лень. Хотя разницы нет (наверное))).
Всем СПАСИБО
0
10.05.2012, 06:36
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
10.05.2012, 06:36
Привет! Вот еще темы с ответами:

Ошибка преобразования типов - C++
В чем именно я ошибся,если код ошибки #include &lt;iostream&gt; #include &lt;stdlib.h&gt; #include &lt;string&gt; #include &lt;ctype.h&gt; using...

ошибка преобразования char - C++
помогите найти ошибку(или исправить): #include&lt;iostream&gt; #include&lt;string.h&gt; #include&lt;conio.h&gt; #include&lt;stdio.h&gt; ...

Ошибка преобразования класса - C++
Добрый день! Уважаемые, помогите пожалуйста найти ошибку. #include &lt;iostream&gt; #include &lt;stdio.h&gt; #include &lt;string.h&gt; #include...

Ошибка в функции преобразования времени - C++
Как можно или нужно написать программу, которая, при вводе с клавиатуры, делает преобразования времени при помощи двух функций. Одна...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
15
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2018, vBulletin Solutions, Inc.