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

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

10.05.2012, 01:35. Показов 3168. Ответов 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
8488 / 6155 / 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
8488 / 6155 / 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
8488 / 6155 / 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
8488 / 6155 / 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
8488 / 6155 / 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
Ответ Создать тему
Новые блоги и статьи
Ритм жизни
kumehtar 27.02.2026
Иногда приходится жить в ритме, где дел становится всё больше, а вовлечения в происходящее — всё меньше. Плотный график не даёт вниманию закрепиться ни на одном событии. Утро начинается с быстрых,. . .
SDL3 для Web (WebAssembly): Сборка библиотек SDL3 и Box2D из исходников с помощью CMake и Emscripten
8Observer8 27.02.2026
Недавно вышла версия SDL 3. 4. 2 библиотеки SDL3. На странице официальной релиза доступны исходники, готовые DLL (для x86, x64, arm64), а также библиотеки для разработки под Android, MinGW и Visual. . .
SDL3 для Web (WebAssembly): Реализация движения на Box2D v3 - трение и коллизии с повёрнутыми стенами
8Observer8 20.02.2026
Содержание блога Box2D позволяет легко создать главного героя, который не проходит сквозь стены и перемещается с заданным трением о препятствия, которые можно располагать под углом, как верхнее. . .
Конвертировать закладки radiotray-ng в m3u-плейлист
damix 19.02.2026
Это можно сделать скриптом для PowerShell. Использование . \СonvertRadiotrayToM3U. ps1 <path_to_bookmarks. json> Рядом с файлом bookmarks. json появится файл bookmarks. m3u с результатом. # Check if. . .
Семь CDC на одном интерфейсе: 5 U[S]ARTов, 1 CAN и 1 SSI
Eddy_Em 18.02.2026
Постепенно допиливаю свою "многоинтерфейсную плату". Выглядит вот так: https:/ / www. cyberforum. ru/ blog_attachment. php?attachmentid=11617&stc=1&d=1771445347 Основана на STM32F303RBT6. На борту пять. . .
Камера Toupcam IUA500KMA
Eddy_Em 12.02.2026
Т. к. у всяких "хикроботов" слишком уж мелкий пиксель, для подсмотра в ESPriF они вообще плохо годятся: уже 14 величину можно рассмотреть еле-еле лишь на экспозициях под 3 секунды (а то и больше),. . .
И ясному Солнцу
zbw 12.02.2026
И ясному Солнцу, и светлой Луне. В мире покоя нет и люди не могут жить в тишине. А жить им немного лет.
«Знание-Сила»
zbw 12.02.2026
«Знание-Сила» «Время-Деньги» «Деньги -Пуля»
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru