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

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

Войти
Регистрация
Восстановить пароль
 
Рейтинг: Рейтинг темы: голосов - 9, средняя оценка - 4.67
VisualNIK
8 / 8 / 1
Регистрация: 29.10.2012
Сообщений: 168
#1

Объясните ситуацию с integer, float и double. Выводится число на единицу меньше положенного - C++

17.03.2014, 14:37. Просмотров 1258. Ответов 10
Метки нет (Все метки)

Здравствуйте. Хотел бы разузнать, в чем дело в следующей ситуации:

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
28
29
void excs_fifteen()
{
    system("cls");
 
    cout<<"-> Exercise 15\n\n";
 
    int n;
 
    cout<<"n = ";
    cin>>n;
 
    cout<<"\n\nNumbers = ";
 
    for(int i = 1; i <= n; i++)
    {
        int size = 1;  float num_sq = i*i;
        
        while(int(num_sq / 10) != 0)
        {
            num_sq = num_sq / 10;
            size *= 10;
        }
        
        float g = (num_sq - int(num_sq)) * size;
        
        cout<<g<<"  ";
    } 
 
    getch();
при таком расскладе выводит все как нужно, но если я делаю так

C++
1
cout<<int(g)<<"  ";
то выводится число на единицу меньше (вместо шести - пять, например)....примечательно, что если объявить переменные num_sq и g типа double, то все на ладу, и выводятся нужные значения....хотел расковырять этот момент, каких-либо ошибок не вижу, за исключением, возможно, моего непонимания какого-то аспекта. Спасибо!
0
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
17.03.2014, 14:37
Здравствуйте! Я подобрал для вас темы с ответами на вопрос Объясните ситуацию с integer, float и double. Выводится число на единицу меньше положенного (C++):

Преобразовать 2 числа int в 1 число float(double) | double int1.int2 - C++
Всем привет. Изучая азы C++, столкнулся с такой проблемой. Есть два значения типа int, их необходимо преобразовать в одно значение типа...

Объясните понятно пожалуйста float и double - C++
Для чего они и как ими пользоваться?

Почему при преобразования из float в double коверкается число? - C++
float fll=34.23; cout &lt;&lt; &quot; fll=&quot;&lt;&lt; fll; //Вот тут я ввожу double dub; dub = (double)fll;cout&lt;&lt;&quot; dub=&quot;&lt;&lt;dub; // А вот тут оно уже :...

Как проверить вводилось ли число (типа double или float) в консоль - C++
Как проверить вводилось ли число (типа double или float) в консоль?

Число байт для Double/Float - C#
Пишу задачи на типизированные файлы. Необходимо использовать переменную типа Double или Float дли зписи средней оценки стулента. Скажите,...

Перевод из двоичной СС в десятичную: выводится число на 1 меньше - C (СИ)
Здравствуйте! Есть примитивная функция преобразования двоичного числа в десятичное: unsigned BinToDec(char* bin) { int i; ...

Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Tulosba
:)
Эксперт С++
4396 / 3239 / 297
Регистрация: 19.02.2013
Сообщений: 9,045
17.03.2014, 14:52 #2
Цитата Сообщение от nvdrossii Посмотреть сообщение
то выводится число на единицу меньше (вместо шести - пять, например)
На какой итерации цикла?
0
zss
Модератор
Эксперт С++
6382 / 5947 / 1927
Регистрация: 18.12.2011
Сообщений: 15,264
Завершенные тесты: 1
17.03.2014, 15:33 #3
Поменяйте float На double.
Поскольку все вычисления процессора идут с точностью double,
то дополнительные преобразование во float и обратно в double
приводят к потере точности.
1
VisualNIK
8 / 8 / 1
Регистрация: 29.10.2012
Сообщений: 168
17.03.2014, 15:56  [ТС] #4
zss, благодарю вас, был бы признателен, если бы раскрыли тонкости применения double и float...так например я заметил что в некоторых случаях когда я использовал double вместо float в типичных задачка с матрицами, в результате у меня в выводе была чушь -9000909090909090.000000000009 и вроде этого, менял на float и все было в ажуре...

Добавлено через 1 минуту
Tulosba, дело не в цикле, но double действительно решил, для внесения ясности опишу условия задачи и нынешний (рабочий вариант):

Дано натуральное число n. Среди чисел 1, ..., n найти все такие, запись которых совпадает с последними цифрами записи их квадрата (как, например, б^2 =36, 25^2=625 и т. д.).

Решение:

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
28
system("cls");
 
    cout<<"-> Exercise 15\n\n";
 
    int n;
 
    cout<<"n = ";
    cin>>n;
 
    cout<<"\n\nNumbers = ";
 
    for(int i = 1; i <= n; i++)
    {
        int size = 1;  double num_sq = i*i;
        
        while(int(num_sq / 10) != 0)
        {
            num_sq = num_sq / 10;
            size *= 10;
        }
        
        double g = (num_sq - int(num_sq)) * size;
        
        if(i == int(g))
            cout<<i<<"  ";
    } 
 
    getch();
Добавлено через 4 минуты
Tulosba, хотя быть может и в цикле, например 625^2 = 390625 а его не выводит! сейчас разберусь
0
zss
Модератор
Эксперт С++
6382 / 5947 / 1927
Регистрация: 18.12.2011
Сообщений: 15,264
Завершенные тесты: 1
17.03.2014, 16:00 #5
Соображение простые.
поскольку num_sq имеет тип float, то
выполняются следующие действия
C++
1
num_sq = num_sq / 10;
1. Преобразование num_sq в double
2. Преобразование 10 в double
3. Деление
4. Преобразование во float
Это повторяется в цикле.
В результате и накапливается ошибка округления.
0
VisualNIK
8 / 8 / 1
Регистрация: 29.10.2012
Сообщений: 168
17.03.2014, 17:58  [ТС] #6
zss, там накосячил и в самом принципе программы, переделал, теперь она выглядит следующим образом:

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
28
    system("cls");
 
    cout<<"-> Exercise 15\n\n";
 
    int n;
 
    cout<<"n = ";
    cin>>n;
 
    cout<<"\n\nNumbers = ";
 
    for(int i = 1; i <= n; i++)
    {
        int size = 10;  int num = i; double num_sq = i*i;
        
        while(int(num / 10) != 0)
        {
            num /= 10;
            size *= 10;
        }
        
        int g = ((num_sq / size) - int(num_sq / size))*size;
        
        if(i == g)
            cout<<i<<"  ";
    } 
 
    getch();
только вот не известно все ли выдаются значения...но выдает теперь из тысячи 6 чисел....да и если не сложно по аналогии какие действия происходят в формуле g = ... что куда там преобразовывается..интересно знать

Добавлено через 1 час 44 минуты
В итоге обнаружил нехватку ещё одного числа в выводе, сделал так и теперь выводит ещё пару чисел. Получилось так:

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
28
    system("cls");
 
    cout<<"-> Exercise 15\n\n";
 
    int n;
 
    cout<<"n = ";
    cin>>n;
 
    cout<<"\n\nNumbers = ";
 
    for(int i = 1; i <= n; i++)
    {
        int size = 10;  int num = i; int num_sq = i*i;
        
        while(int(num / 10) != 0)
        {
            num /= 10;
            size *= 10;
        }
        
        int g = num_sq % size;
        
        if(i == g)
            cout<<i<<"  ";
    } 
 
    getch();
Теперь все переменные типа int, в таком случае потери точности быть не должно?
0
DrOffset
7152 / 4293 / 968
Регистрация: 30.01.2014
Сообщений: 7,095
17.03.2014, 18:32 #7
Цитата Сообщение от zss Посмотреть сообщение
1. Преобразование num_sq в double
2. Преобразование 10 в double
С чего бы вдруг?

Добавлено через 6 минут
5/9
The purpose is to yield a common type, which is also the type of the result.
This pattern is called the usual arithmetic conversions, which are defined as follows:
— If either operand is of scoped enumeration type (7.2), no conversions are performed; if the other
operand does not have the same type, the expression is ill-formed.
— If either operand is of type long double, the other shall be converted to long double.
— Otherwise, if either operand is double, the other shall be converted to double.
Otherwise, if either operand is float, the other shall be converted to float.
— Otherwise, the integral promotions (4.5) shall be performed on both operands.
Then the following rules shall be applied to the promoted operands:
— If both operands have the same type, no further conversion is needed.
— Otherwise, if both operands have signed integer types or both have unsigned integer types, the
operand with the type of lesser integer conversion rank shall be converted to the type of the
operand with greater rank.
— Otherwise, if the operand that has unsigned integer type has rank greater than or equal to the
rank of the type of the other operand, the operand with signed integer type shall be converted to
the type of the operand with unsigned integer type.
— Otherwise, if the type of the operand with signed integer type can represent all of the values of
the type of the operand with unsigned integer type, the operand with unsigned integer type shall
be converted to the type of the operand with signed integer type.
— Otherwise, both operands shall be converted to the unsigned integer type corresponding to the
type of the operand with signed integer type.
В соответствии с выделенным тут будет только одно преобразование: 10 к float. И все.
1
zss
Модератор
Эксперт С++
6382 / 5947 / 1927
Регистрация: 18.12.2011
Сообщений: 15,264
Завершенные тесты: 1
17.03.2014, 19:11 #8
Цитата Сообщение от DrOffset Посмотреть сообщение
С чего бы вдруг?
Я имею ввиду, что процессор ПК работает с числами double.
Поэтому float приходится преобразовывать в double
(а уж int (десятку) тем более).
Для мобильных процессоров это скорее всего не так.
0
DrOffset
7152 / 4293 / 968
Регистрация: 30.01.2014
Сообщений: 7,095
17.03.2014, 21:12 #9
Цитата Сообщение от zss Посмотреть сообщение
что процессор ПК работает с числами double.
Вычисления на FPU в x86 могут иметь три варианта точности: 32, 64, (80 или 128) бит. Откуда вывод, что ПК работает именно с double? Точность согласно стандарта IEEE-754, выставляется флагом PC. Который, по-умолчанию, выставляет точность в максимальное значение, что уже противоречит тезису, если считать, что double - 64 бита. Отсюда закономерный вопрос: что вообще такое double с точки зрения ПК с учетом того, что стандарт С++ не регламентирует реализацию плавающей точки?

Точность плавающей точки теряется либо на понижающих преобразованиях, либо из-за особенностей представления, когда число не представимо в виде конечной двоичной дроби.

Вот я еще и примерчик накидал:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
//mingw 4.7.2 
 
//sizeof(float) == 4
extern float a1;
extern float b1;
 
//sizeof(double) == 8
extern double a2; // extern, чтобы подавить вычисление значения на этапе компиляции, переменные определены в другом файле
extern double b2;
 
void f1()
{
    b1 = a1 / 10;
}
 
void f2()
{
    b2 = a2 / 10;
}
Assembler
1
2
3
4
5
6
7
8
9
10
11
12
f1:
    fld DWORD PTR LC0
    fdivr   DWORD PTR _a1 ; адресуем двойное слово
    fstp    DWORD PTR _b1
    ret
f2:
    fld DWORD PTR LC0 ; заметим, что 10 все еще адресуется как двойное слово
    fdivr   QWORD PTR _a2 ; адресуем четверное слово
    fstp    QWORD PTR _b2
    ret
LC0:
    .long   1092616192 ; это 10
Никаких преобразований тут нет.
2
Tulosba
:)
Эксперт С++
4396 / 3239 / 297
Регистрация: 19.02.2013
Сообщений: 9,045
17.03.2014, 22:03 #10
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <iostream>
#include <cmath>
 
bool pass( int n )
{
    int p = static_cast<int>(std::log10(n))+1;
    return (n*n) % static_cast<int>(std::pow(10,p)) == n;
}
 
int main() {
    
    for( int i=1; i<10000; ++i )
    {
        if( pass(i) ) std::cout << i << std::endl;
    }
    return 0;
}
http://ideone.com/itxo02
1
VisualNIK
8 / 8 / 1
Регистрация: 29.10.2012
Сообщений: 168
18.03.2014, 05:18  [ТС] #11
Tulosba, тут на математике просто завязали.. Спасибо нужно же уметь мыслить не только в глубь н и в ширь...тоже инетерсный вариант....а static_cast<int> это типа преобразование в int, что-то вроде int(log10(n)), я правильно понял?
0
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
18.03.2014, 05:18
Привет! Вот еще темы с ответами:

Как обойтись без float, double, long double? - Программирование
К примеру мне надо в программе использовать что-то вроде -0,00000000000003626686812 и 0,00000000000002072392464. Притом чтобы считалось...

Объясните ситуацию. - C++ WinAPI
Всем доброго времени суток. Не так давно я начал изучать WinAPI и первым делом обратился к Wikipedia. На странице с описанием WinAPI я...

Написать функцию f(x:integer):integer, где x - натуральное число, не более 99, а результат выполнения функции - число букв при написании числа. - Delphi
Написать функцию f(x:integer):integer, где x - натуральное число, не более 99, а результат выполнения функции - число букв при написании...

Перевод строки, содержащей число типа float, в число float - C (СИ)
Помогите разобраться, как строку, к примеру &quot;0.123&quot; перевести в переменную типа float...


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

Или воспользуйтесь поиском по форуму:
Yandex
Объявления
18.03.2014, 05:18
Ответ Создать тему
Опции темы

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