Форум программистов, компьютерный форум CyberForum.ru

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

Восстановить пароль Регистрация
 
 
Рейтинг: Рейтинг темы: голосов - 11, средняя оценка - 4.64
G@leON
 Аватар для G@leON
6 / 6 / 1
Регистрация: 02.06.2009
Сообщений: 95
10.05.2012, 01:35     Ошибка преобразования типа #1
Задача состояла в следующем: реализация алгоритма проверки 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 с получением остатка от деления.
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
Toshkarik
 Аватар для Toshkarik
1139 / 856 / 50
Регистрация: 03.08.2011
Сообщений: 2,381
Завершенные тесты: 1
10.05.2012, 07:23     Ошибка преобразования типа #21

Не по теме:

Цитата Сообщение от G@leON Посмотреть сообщение
А ставить несколько спасибо можно?
За любое показавшееся Вам полезным сообщение.


Посмотрел функцию решета Эратосфена - можно свести к более простому варианту:
C++
1
2
3
4
5
6
vector< bool > vec( number );
fill( vec.begin(), vec.end(), true );
for ( size_t i = 2; i < vec.size(); i++ )
   if ( vec[ i ])
      for( size_t j = i + i; j < vec.size(); j += i )
         vec[ j ] = false;
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
taras atavin
Ушёл с форума.
 Аватар для taras atavin
3569 / 1752 / 91
Регистрация: 24.11.2009
Сообщений: 27,619
10.05.2012, 07:25     Ошибка преобразования типа #22
Цитата Сообщение от Avazart Посмотреть сообщение
Может человек имеет ввиду округление, а не приведение типов?
А чем округление до целого отличается от приведения дроби к целому?
Toshkarik
 Аватар для Toshkarik
1139 / 856 / 50
Регистрация: 03.08.2011
Сообщений: 2,381
Завершенные тесты: 1
10.05.2012, 07:28     Ошибка преобразования типа #23
Цитата Сообщение от taras atavin Посмотреть сообщение
А чем округление до целого отличается от приведения дроби к целому?
Тем, что при округлении берется ближайшее целое, при приведении же просто отбрасывается дробная часть.
taras atavin
Ушёл с форума.
 Аватар для taras atavin
3569 / 1752 / 91
Регистрация: 24.11.2009
Сообщений: 27,619
10.05.2012, 07:44     Ошибка преобразования типа #24
Цитата Сообщение от G@leON Посмотреть сообщение
Оба значение типа long на 1 меньше, чем возвращаемые функциями значения типа double.
А при чём здесь ошибка приведения? Ошибка приведения, это когда вообще нельзя привести. А здесь погрешность округления. Твой double чуть меньше ожидаемого целого.
C++
1
2
3
4
5
6
int x;
int y;
float z;
z=2.5;
x=z;// Округление вниз, x=2
y=z+0.5;// Округление по математическим правилам, y=3
Добавлено через 8 минут
Цитата Сообщение от Toshkarik Посмотреть сообщение
Тем, что при округлении берется ближайшее целое, при приведении же просто отбрасывается дробная часть.
Существует как минимум 4 способа округления: вниз, вверх, по математическим правилам и так называемое банкирское, по правилам которого если дробная часть точно равна 0.5, то округляют к ближайшему чётному, а в остальных случаях к ближайшему целому, при округлении вниз дробная часть отбрасывается, при округлении вверх при ненулевой дробной части инкремируется целая, а при нулевой сохраняется и после этого отбрасывается дробная часть, а оператор приведения типа может быть написан как угодно и предусматривать какое нибудь вообще пятое округление. В любом случае обнуление младших разрядов в какой либо системе счисления есть округление (округлять можно и до сотен, и до сотых), а приведение к целому всегда обнуляет все разряды с весами меньше единицы, что есть округление до целого. То, что встроенные типы принято приводить именно округлением вниз, сути не меняет.

Добавлено через 6 минут
Цитата Сообщение от G@leON Посмотреть сообщение
Я так понимаю, задача вылазит несколько другим боком. Нужно как то умудрится возвести в степень n и n-1 число v_1, а результат потом делить на n с получением остатка от деления.
Если и основание, и показатель целые, то зачем возводить в степень через экспоненту? Для данного случая степень определена, как произведение одинаковых множителей, так и делай.
Toshkarik
 Аватар для Toshkarik
1139 / 856 / 50
Регистрация: 03.08.2011
Сообщений: 2,381
Завершенные тесты: 1
10.05.2012, 07:46     Ошибка преобразования типа #25
Думаю, тут уместно обсуждение математического округления а не каких то там "банкирских" и тд.
Приведение типа, как я считаю, никак не связанно с округлением.
Цитата Сообщение от taras atavin Посмотреть сообщение
написан как угодно
Не как угодно, отбрасывается именно дробная часть.
taras atavin
Ушёл с форума.
 Аватар для taras atavin
3569 / 1752 / 91
Регистрация: 24.11.2009
Сообщений: 27,619
10.05.2012, 07:51     Ошибка преобразования типа #26
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
long int degree(long int a, unsigned int n)// a в степени n
{
 int n1;
 if (n==1)
 {
  return a;
 }
 if (n==0)
 {
  return 1;
 }
 n1=n/2;
 return (degree(a, n1)*degree(a, n-n1)); 
}
, или
C++
1
2
3
4
5
6
7
8
9
long int degree(long int a, unsigned int n)// a в степени n
{
 int r;
 for (r=1; n>0; --n)
 {
  r*=a;
 }
 return r; 
}
Добавлено через 3 минуты
Цитата Сообщение от Toshkarik Посмотреть сообщение
Не как угодно, отбрасывается именно дробная часть.
Как угодно. Конкретный способ принят только для стандартных типов и является всего лишь вопросом выбора авторов стандарта. Для своих типов ты можешь сделать даже так: если дробная часть строго меньше 0.5, то вверх, иначе вниз. И это тоже будет округление. Или можешь сделать математическое округление до кратного трём.
Toshkarik
 Аватар для Toshkarik
1139 / 856 / 50
Регистрация: 03.08.2011
Сообщений: 2,381
Завершенные тесты: 1
10.05.2012, 07:54     Ошибка преобразования типа #27
При чем тут не стандартные типы? Вы тут видите приведение не стандартных типов? Для стандартных типов точно указано, что получится в итоге, и это никак не связанно с округлением. Это форум С++, если Вы вдруг упустили это из виду.
taras atavin
Ушёл с форума.
 Аватар для taras atavin
3569 / 1752 / 91
Регистрация: 24.11.2009
Сообщений: 27,619
10.05.2012, 08:03     Ошибка преобразования типа #28
Для стандартных был выбран один из способов округления, выбор закрепили. И всего делов. Приведение стандартного вещественного к целому, это округление вниз до целого, а не что то абсолютно новое.
Toshkarik
 Аватар для Toshkarik
1139 / 856 / 50
Регистрация: 03.08.2011
Сообщений: 2,381
Завершенные тесты: 1
10.05.2012, 08:07     Ошибка преобразования типа #29
Я же считаю, что данный способ был выбран исходя из природы чисел. Целое на то и целое, что в нем нет дробной части, поэтому она отбрасывается, и это не округление.
G@leON
 Аватар для G@leON
6 / 6 / 1
Регистрация: 02.06.2009
Сообщений: 95
10.05.2012, 08:18  [ТС]     Ошибка преобразования типа #30
За решето спасибо, удобный способ, по поводу приведения типов, это именно ошибка приведения, просто это не ошибка синтаксиса, а ошибка компиляции некрасивой логики. И да, именно с округлением она и связана, так что в формулировке не вижу повода сомневаться.

По поводу параметра ссылки, а какая разница, передаете вы через параметр-ссылку, или просто возвращаете значение? Если вопрос удобства, то мне удобней через параметр-ссылку (либо параметр-указатель). Мне так логика понятней кажется.
taras atavin
Ушёл с форума.
 Аватар для taras atavin
3569 / 1752 / 91
Регистрация: 24.11.2009
Сообщений: 27,619
10.05.2012, 08:20     Ошибка преобразования типа #31
Это именно округление. Отбрасывание дробной части есть округление вниз. А по какому принципу выбирали - вторично. Мне кажется, что выбрали вниз потому, что так проще. Но мотив выбора реализации не имеет ни какого отношения к наименованию операции.
Toshkarik
 Аватар для Toshkarik
1139 / 856 / 50
Регистрация: 03.08.2011
Сообщений: 2,381
Завершенные тесты: 1
10.05.2012, 08:23     Ошибка преобразования типа #32
taras atavin, пусть каждый останется при своем мнении. Я по другому смотрю на приведение типа в данном случае, и оно никак не вяжется с округлением.
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
10.05.2012, 17:41     Ошибка преобразования типа
Еще ссылки по теме:

C++ Ошибка преобразования класса
Ошибка в функции преобразования времени C++
Преобразования массива с типа int к типу char C++

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

Или воспользуйтесь поиском по форуму:
Avazart
 Аватар для Avazart
6900 / 5140 / 252
Регистрация: 10.12.2010
Сообщений: 22,587
Записей в блоге: 17
10.05.2012, 17:41     Ошибка преобразования типа #33
Не путайте округление к ближайшему целому (то к которому нас в школе учили) и округление к меньшему(то которое предусмотрено ф-цией floor(), и впринципе происходит при в данном случаее при приведении).

И дело не в не правильном приведении типов, а в незнании того к чему оно приводит....

http://ru.wikipedia.org/wiki/Округление
Yandex
Объявления
10.05.2012, 17:41     Ошибка преобразования типа
Ответ Создать тему
Опции темы

Текущее время: 14:10. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2016, vBulletin Solutions, Inc.
Рейтинг@Mail.ru