С Новым годом! Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.54/13: Рейтинг темы: голосов - 13, средняя оценка - 4.54
 Аватар для G@leON
6 / 6 / 2
Регистрация: 02.06.2009
Сообщений: 99

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

10.05.2012, 01:35. Показов 3105. Ответов 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
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
10.05.2012, 01:35
Ответы с готовыми решениями:

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

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

Оператор преобразования типа в классах
Допустим, есть три класса: //Фигура class figure; //Дамка class king { public: void step(figure&amp;);

32
Эксперт С++
 Аватар для Avazart
8484 / 6151 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
10.05.2012, 05:18
Что такое exp() и где оно живет?
0
 Аватар для G@leON
6 / 6 / 2
Регистрация: 02.06.2009
Сообщений: 99
10.05.2012, 05:32  [ТС]
Она из заголовка <math.h>
Давай так. Что бы проще было, вкладываю код юнита, заголовка и собственно main.
Вложения
Тип файла: rar Библиотеки проверки на простоту.rar (1.5 Кб, 6 просмотров)
0
 Аватар для Toshkarik
1181 / 894 / 94
Регистрация: 03.08.2011
Сообщений: 2,461
10.05.2012, 05:48
Avazart, exp()
Это вот эта теорема?
0
Эксперт С++
 Аватар для Avazart
8484 / 6151 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
10.05.2012, 06:02
У мня компилится без ошибок...

Добавлено через 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 / 2
Регистрация: 02.06.2009
Сообщений: 99
10.05.2012, 06:07  [ТС]
Компилитс без ошибок, я вообщето писал что все ОК.
Ошибка в преобразовании. Преобразование он делает, но теряет 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
8484 / 6151 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
10.05.2012, 06:14
Что значит "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
1181 / 894 / 94
Регистрация: 03.08.2011
Сообщений: 2,461
10.05.2012, 06:16
Так Вы уж определитесь, с какими типами работаете, не удивительно, что есть погрешность при преобразовании вещественного типа в целочисленный.
0
 Аватар для G@leON
6 / 6 / 2
Регистрация: 02.06.2009
Сообщений: 99
10.05.2012, 06:19  [ТС]
Мне дальше надо делить с получением остатка. Поэтому мне надо получить целочисленное.
Ни 1 из вещественных типов не обрабатывается оператором %.

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

И я понимаю, что это некрасиво. С точки зрения машины все правильно, но я то понимаю, что есть погрешность при преобразовании вещественного типа в целочисленный. Просто тип double не делится с остатком))
0
 Аватар для Toshkarik
1181 / 894 / 94
Регистрация: 03.08.2011
Сообщений: 2,461
10.05.2012, 06:21
Для этого есть функция fmod().
0
Эксперт С++
 Аватар для Avazart
8484 / 6151 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
10.05.2012, 06:21
Может человек имеет ввиду округление, а не приведение типов?
0
 Аватар для Toshkarik
1181 / 894 / 94
Регистрация: 03.08.2011
Сообщений: 2,461
10.05.2012, 06:22
А чем при возведении в степень не устроила функция pow()?
0
Эксперт С++
 Аватар для Avazart
8484 / 6151 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
10.05.2012, 06:24
Выглядит не так страшно
1
 Аватар для Toshkarik
1181 / 894 / 94
Регистрация: 03.08.2011
Сообщений: 2,461
10.05.2012, 06:27

Не по теме:

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 / 2
Регистрация: 02.06.2009
Сообщений: 99
10.05.2012, 06:36  [ТС]
Во, fmod - то, что нужно.
floor - это тоже хорошо.
А функция pow(), она конечно хороша, просто такая форма возведения мне понятна. А код pow() мне смотреть лень. Хотя разницы нет (наверное))).
Всем СПАСИБО
0
 Аватар для Toshkarik
1181 / 894 / 94
Регистрация: 03.08.2011
Сообщений: 2,461
10.05.2012, 06:39
Цитата Сообщение от G@leON Посмотреть сообщение
Хотя разницы нет (наверное)
Скорей всего есть. Использование pow() имеет вид:
double pow( base, exponent );
То-есть в Вашем случае просто нужно было написать
C++
1
long l_v1 = pow( v_1, n );
1
 Аватар для G@leON
6 / 6 / 2
Регистрация: 02.06.2009
Сообщений: 99
10.05.2012, 06:52  [ТС]
Цитата Сообщение от Toshkarik Посмотреть сообщение
Скорей всего есть. Использование pow() имеет вид:
double pow( base, exponent );
То-есть в Вашем случае просто нужно было написать
C++
1
long l_v1 = pow( v_1, n );
Кстати да, попробовал предсавленный код, он тоже верный. Но......
И использовать его проще, что б нафиг на парится)) Оставлю с pow(). Все таки странно. exp() преобразуется с потерей 1 в значении. А после pow() все замечательно. Как так?
0
 Аватар для Toshkarik
1181 / 894 / 94
Регистрация: 03.08.2011
Сообщений: 2,461
10.05.2012, 07:03
Вещественные числа в компьютерных системах представляются приблизительно. Они не могут быть точными в отличии от целых чисел. Вы вызываете функцию log внутри exp, что только усугубляет положение. При присваивании вещественного типа целочисленному отбрасывается дробная часть. Могу предположить, что в данном случае получалось, например, число вроде 18.9234... и так далее, что при приведении давало целое 18 вместо 19. Поэтому Вам подкинул идею с функцией floor, которая округляет вещественное число до наибольшего целого не превосходящее само число. Ее часто используют для округления вещественного числа до ближайшего целого в виде
floor( val + .5 );
0
 Аватар для G@leON
6 / 6 / 2
Регистрация: 02.06.2009
Сообщений: 99
10.05.2012, 07:14  [ТС]
Цитата Сообщение от Toshkarik Посмотреть сообщение
Вещественные числа в компьютерных системах представляются приблизительно. Они не могут быть точными в отличии от целых чисел. Вы вызываете функцию log внутри exp, что только усугубляет положение. При присваивании вещественного типа целочисленному отбрасывается дробная часть. Могу предположить, что в данном случае получалось, например, число вроде 18.9234... и так далее, что при приведении давало целое 18 вместо 19. Поэтому Вам подкинул идею с функцией floor, которая округляет вещественное число до наибольшего целого не превосходящее само число. Ее часто используют для округления вещественного числа до ближайшего целого в виде
floor( val + .5 );
Ага, понятно, по крайне мере удалось выяснить методом научного втыка, что применение ф-ции fmod() иже с ней требует ф-ции floor(), без нее сравнения не получается.

Не по теме:

А ставить несколько спасибо можно? А то меня порадовало конечно :yahoo:.

0
 Аватар для taras atavin
4226 / 1796 / 211
Регистрация: 24.11.2009
Сообщений: 27,562
10.05.2012, 07:23
Цитата Сообщение от G@leON Посмотреть сообщение
адача состояла в следующем: реализация алгоритма проверки n на простоту, используя малую теорему Ферма. В силу недостаточного опыта и позднего времени накумекал следующий код с пояснениями:
В качестве 1 из параметров, передаваемых функциям, выступает маркер простоты.
Это параметр-ссылка на переменную логического типа.
Значение маркера = true после выполнения подтверждает простоту проверяемого числа.
Зачем здесь лишний параметр? Проще возвращать по имени самой функции ретоном и не мучаться.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
10.05.2012, 07:23
Помогаю со студенческими работами здесь

Оператор преобразования типа в char*
Всем привет! Вот у меня есть готовый код для класса Complex #include &lt;iostream&gt; #include &lt;cmath&gt; using namespace std; ...

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

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

Массивы и строки: реализовать метод ldtoms() для преобразования числа типа long double в денежную строку
Вернемся к обсуждению денежных строк из упражнения 6. Напишите ме- тод ldtoms() для преобразования числа типа long double в денежную...

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


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

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Новые блоги и статьи
Почему дизайн решает?
Neotwalker 09.01.2026
В современном мире, где конкуренция за внимание потребителя достигла пика, дизайн становится мощным инструментом для успеха бренда. Это не просто красивый внешний вид продукта или сайта — это. . .
Модель микоризы: классовый агентный подход 3
anaschu 06.01.2026
aa0a7f55b50dd51c5ec569d2d10c54f6/ O1rJuneU_ls https:/ / vkvideo. ru/ video-115721503_456239114
Owen Logic: О недопустимости использования связки «аналоговый ПИД» + RegKZR
ФедосеевПавел 06.01.2026
Owen Logic: О недопустимости использования связки «аналоговый ПИД» + RegKZR ВВЕДЕНИЕ Введу сокращения: аналоговый ПИД — ПИД регулятор с управляющим выходом в виде числа в диапазоне от 0% до. . .
Модель микоризы: классовый агентный подход 2
anaschu 06.01.2026
репозиторий https:/ / github. com/ shumilovas/ fungi ветка по-частям. коммит Create переделка под биомассу. txt вход sc, но sm считается внутри мицелия. кстати, обьем тоже должен там считаться. . . .
Расчёт токов в цепи постоянного тока
igorrr37 05.01.2026
/ * Дана цепь постоянного тока с сопротивлениями и напряжениями. Надо найти токи в ветвях. Программа составляет систему уравнений по 1 и 2 законам Кирхгофа и решает её. Последовательность действий:. . .
Новый CodeBlocs. Версия 25.03
palva 04.01.2026
Оказывается, недавно вышла новая версия CodeBlocks за номером 25. 03. Когда-то давно я возился с только что вышедшей тогда версией 20. 03. С тех пор я давно снёс всё с компьютера и забыл. Теперь. . .
Модель микоризы: классовый агентный подход
anaschu 02.01.2026
Раньше это было два гриба и бактерия. Теперь три гриба, растение. И на уровне агентов добавится между грибами или бактериями взаимодействий. До того я пробовал подход через многомерные массивы,. . .
Советы по крайней бережливости. Внимание, это ОЧЕНЬ длинный пост.
Programma_Boinc 28.12.2025
Советы по крайней бережливости. Внимание, это ОЧЕНЬ длинный пост. Налог на собак: https:/ / **********/ gallery/ V06K53e Финансовый отчет в Excel: https:/ / **********/ gallery/ bKBkQFf Пост отсюда. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru