Модераторы: bsa
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Проблема с pow(), cmath 
:(
    Опции темы
mistrmax
Дата 14.12.2011, 18:48 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 77
Регистрация: 30.5.2010

Репутация: нет
Всего: нет



Здравствуйте. Задача: написать программу для нахождения всех Пифагоровых троек от 1 до 500. Делаю так:
Код

//Пифагоровы тройки
#include <iostream>
#include <cmath>

using namespace std;
int main() {
    for (int i = 1; i <= 500; i++) {
        for (int j = 1; j <= 500; j++) {
            for (int k = 1; k <= 500; k++) {
                if (pow(i,2) == (pow(i,2) + pow(k,2))) {
                    cout << i << "^2 = " << j << "^2 + " << k << "^2 \n";
                }
            }
        }
    }
    cin.get();
    return 0;
}

Компилятор (MV C++ 2010) сообщает об ошибке выполнения функции pow(). Почитал в документации, и, насколько я понял, x и y [pow(x,y)] должны быть или double или float, в данном случае они int, но ведь происходит преобразование типов, так что... Подскажите в чём проблема пожалуйста. Заранее благодарен.
PM   Вверх
rumit7
Дата 14.12.2011, 19:47 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 71
Регистрация: 16.6.2011

Репутация: нет
Всего: 7



Цитата(mistrmax @ 14.12.2011,  18:48)
Здравствуйте. Задача: написать программу для нахождения всех Пифагоровых троек от 1 до 500. Делаю так:
Код

//Пифагоровы тройки
#include <iostream>
#include <cmath>

using namespace std;
int main() {
    for (int i = 1; i <= 500; i++) {
        for (int j = 1; j <= 500; j++) {
            for (int k = 1; k <= 500; k++) {
                if (pow(i,2) == (pow(i,2) + pow(k,2))) {
                    cout << i << "^2 = " << j << "^2 + " << k << "^2 \n";
                }
            }
        }
    }
    cin.get();
    return 0;
}

Компилятор (MV C++ 2010) сообщает об ошибке выполнения функции pow(). Почитал в документации, и, насколько я понял, x и y [pow(x,y)] должны быть или double или float, в данном случае они int, но ведь происходит преобразование типов, так что... Подскажите в чём проблема пожалуйста. Заранее благодарен.

в данном случае компилятор не знает во что ему сконвертить int во float или в double, для него эти два преобразования типов равнозначны. Поэтому не знает какую версию pow() вызвать, ту что для float или double?

Нужно ему помочь используя явное преобразование типов: pow( (double)i, (double)2).

В вашем случае можно проще: pow(i, 2.0), и в данном случае он вызовет pow(double, double).

Подробнее об преобразованиях типов (явных, неявных) и выборе соот. перегруженной функции читайте у Липпмана "С++ для начинающих".
PM MAIL   Вверх
mistrmax
Дата 15.12.2011, 07:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 77
Регистрация: 30.5.2010

Репутация: нет
Всего: нет



Здравствуйте, спасибо за ответ. Сделал как вы и сказали и всё заработало. Спасибо.
PM   Вверх
rumit7
Дата 15.12.2011, 09:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 71
Регистрация: 16.6.2011

Репутация: нет
Всего: 7



Цитата(mistrmax @ 15.12.2011,  07:45)
Здравствуйте, спасибо за ответ. Сделал как вы и сказали и всё заработало. Спасибо.

Знаю, что читать все равно никто не будет, приведу отрывок:

Цитата

При разрешении перегрузки функции выполняются следующие шаги:
1.    Выделяется множество перегруженных функций для данного вызова, а также свойства списка аргументов, переданных функции.
2.    Выбираются те из перегруженных функций, которые могут быть вызваны с данными аргументами, с учетом их количества и типов.
3.    Находится функция, которая лучше всего соответствует вызову.

Рассмотрим последовательно каждый пункт.

На первом шаге необходимо идентифицировать множество перегруженных функций, которые будут рассматриваться при данном вызове. Вошедшие в это множество функции называются кандидатами. Функция кандидат – это функция с тем же именем, что и вызванная, причем ее объявление видимо в точке вызова. 

После этого идентифицируются свойства списка переданных аргументов, т.е. их количество и типы. В нашем примере список состоит из двух аргументов типа double.
На втором шаге среди множества кандидатов отбираются устоявшие (viable) – такие, которые могут быть вызваны с данными аргументами, Устоявшая функция либо имеет столько же формальных параметров, сколько фактических аргументов передано вызванной функции, либо больше, но тогда для каждого дополнительного параметра должно быть задано значение по умолчанию. Чтобы функция считалась устоявшей, для любого фактического аргумента, переданного при вызове, обязано существовать преобразование к типу формального параметра, указанного в объявлении.

Если после второго шага не нашлось устоявших функций, то вызов считается ошибочным. В таких случаях мы говорим, что имеет место отсутствие соответствия.
Третий шаг заключается в выборе функции, лучше всего отвечающей контексту вызова. Такая функция называется наилучшей из устоявших (или наиболее подходящей). На этом шаге производится ранжирование преобразований, использованных для приведения типов фактических аргументов к типам формальных параметров устоявшей функции. Наиболее подходящей считается функция, для которой выполняются следующие условия:

    - преобразования, примененные к фактическим аргументам, не хуже преобразований, необходимых для вызова любой другой устоявшей функции;
    - для некоторых аргументов примененные преобразования лучше, чем преобразования, необходимые для приведения тех же аргументов в вызове других устоявших функций.


Надеюсь С.Липпман не обидится за рекламу его книги..
PM MAIL   Вверх
xvr
Дата 15.12.2011, 14:11 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

Репутация: 35
Всего: 223



Так, кстати - конструкция i*i будет выполняться на порядки быстрее, чем pow(i,2)  smile 


PM MAIL   Вверх
mistrmax
Дата 15.12.2011, 19:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 77
Регистрация: 30.5.2010

Репутация: нет
Всего: нет



xvr, после того, как функция не заработала, так и сделал, но любопытство взяло верх и я решил разобраться в чём дело.

rumit7, тяжёло пишет этот ваш Липпман. Прочитал перегрузку функций у Дейтелов.

rumit7, с вашим вариантом всё заработало, но я так ничего и не понял, даже прочитав цитату из книги и пару статей.

Цитата(rumit7 @  14.12.2011,  19:47 Найти цитируемый пост)
Нужно ему помочь используя явное преобразование типов: pow( (double)i, (double)2).


Тут понятно, мы используем явное приведение типов.

Цитата(rumit7 @  14.12.2011,  19:47 Найти цитируемый пост)
В вашем случае можно проще: pow(i, 2.0), и в данном случае он вызовет pow(double, double).

А что тут? i у нас int, а 2.0 может быть как double, так и float, но тут почему-то компилятор не путается. Обьясните пожалуйста попроще, если можно.


Это сообщение отредактировал(а) mistrmax - 15.12.2011, 19:07
PM   Вверх
rumit7
Дата 15.12.2011, 20:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 71
Регистрация: 16.6.2011

Репутация: нет
Всего: 7



Цитата(mistrmax @ 15.12.2011,  19:07)
rumit7, тяжёло пишет этот ваш Липпман. Прочитал перегрузку функций у Дейтелов.

Да, для начинающего тяжеловато, хоть книга и называется  "С++ для начинающих". Зато все нюансы раскрывает и понимаешь что и почему так! Рекомендую обязательно прочесть, если не сейчас, то чуть позже..

Цитата(mistrmax @ 15.12.2011,  19:07)
rumit7, с вашим вариантом всё заработало, но я так ничего и не понял, даже прочитав цитату из книги и пару статей.

Найдите в 3-ем издании именно тот раздел, отрывок из которого я выше приводил. Ниже я попробую объяснить своими словами, но в книге по любому объясняется по науке. 

Цитата(mistrmax @ 15.12.2011,  19:07)
Цитата(rumit7 @  14.12.2011,  19:47 Найти цитируемый пост)
В вашем случае можно проще: pow(i, 2.0), и в данном случае он вызовет pow(double, double).

А что тут? i у нас int, а 2.0 может быть как double, так и float, но тут почему-то компилятор не путается. Обьясните пожалуйста попроще, если можно.

Попробую, только строго не судите, сочинения в школе за меня писала сестра)

Итак, по Липпману: 
  •  после первого шага у нас имеются 2 функции кандидата - pow(float, float) и pow(double, double). Напомню, что "Функция кандидат – это функция с тем же именем, что и вызванная, причем ее объявление видимо в точке вызова.";
  •  на втором шаге среди множества кандидатов отбираются устоявшие (viable) – такие, которые могут быть вызваны с данными аргументами. Как мы видим обе функции кандидата могут быть вызваны с фактическими аргументами (в нашем случае это i и 2.0);
  •  третий шаг заключается в выборе функции, лучше всего отвечающей контексту вызова. Здесь нужно выбрать функцию, для вызова которой компилятору нужно выполнить меньшее количество преобразований типов. Как видно компилятор тоже ленивый). 

    Смотрим на примере:

    pow(i, 2.0); 

    здесь 1-ый аргумент имеет тип int, а второй аргумент тип double (в С++ все константы типа 3.14 по умолчанию имеют тип double, если только вы явно не укажите другого, например 3.14F или 3.14f - это float, 3.14L или 3.14l - это long double).

    Выберем для какой из 2-х устоявших функций, наши аргументы подходят лучше всего.

    Итак, для вызова pow(float, float) нам необходимо: первый аргумент преобразовать из типа int в тип float, второй аргумент из типа double в  тип float. Итого 2 преобразования.
     
    Для вызова pow(double, double) нам необходимо: первый аргумент преобразовать из типа int в тип double, а для второго никаких преобразований не нужно, у нас второй аргумент итак double. Итого всего лишь 1 преобразование, а это значит данный вызов выигрывает соревнование. Поздравляем победителя!!!

    Таким же образом компилятор выбрал pow(double, double).

PM MAIL   Вверх
mistrmax
Дата 15.12.2011, 20:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 77
Регистрация: 30.5.2010

Репутация: нет
Всего: нет



rumit7, благодарю за обьяснение! Всё очень доходчиво и понятно. Обязательно почитаю Липпмана.
PM   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "C/C++: Для новичков"
JackYF
bsa

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, JackYF, bsa.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Для новичков | Следующая тема »


 




[ Время генерации скрипта: 0.0482 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.