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

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

Восстановить пароль Регистрация
 
Рейтинг: Рейтинг темы: голосов - 9, средняя оценка - 4.67
VisualNIK
 Аватар для VisualNIK
8 / 8 / 1
Регистрация: 29.10.2012
Сообщений: 168
17.03.2014, 14:37     Объясните ситуацию с integer, float и double. Выводится число на единицу меньше положенного #1
Здравствуйте. Хотел бы разузнать, в чем дело в следующей ситуации:

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, то все на ладу, и выводятся нужные значения....хотел расковырять этот момент, каких-либо ошибок не вижу, за исключением, возможно, моего непонимания какого-то аспекта. Спасибо!
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
17.03.2014, 14:37     Объясните ситуацию с integer, float и double. Выводится число на единицу меньше положенного
Посмотрите здесь:

Почему при преобразования из float в double коверкается число? C++
C++ Реализация классов integer, double
Написать программу, реализует следующую игровую ситуацию: компьютер задает случайное целое число в интерали от 1 до 10, а мне нужно это число угадать C++
C++ Объясните понятно пожалуйста float и double
float double int C++
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
Tulosba
:)
Эксперт С++
4378 / 3221 / 297
Регистрация: 19.02.2013
Сообщений: 9,044
17.03.2014, 14:52     Объясните ситуацию с integer, float и double. Выводится число на единицу меньше положенного #2
Цитата Сообщение от nvdrossii Посмотреть сообщение
то выводится число на единицу меньше (вместо шести - пять, например)
На какой итерации цикла?
zss
Модератор
Эксперт С++
 Аватар для zss
5946 / 5551 / 1784
Регистрация: 18.12.2011
Сообщений: 14,181
Завершенные тесты: 1
17.03.2014, 15:33     Объясните ситуацию с integer, float и double. Выводится число на единицу меньше положенного #3
Поменяйте float На double.
Поскольку все вычисления процессора идут с точностью double,
то дополнительные преобразование во float и обратно в double
приводят к потере точности.
VisualNIK
 Аватар для VisualNIK
8 / 8 / 1
Регистрация: 29.10.2012
Сообщений: 168
17.03.2014, 15:56  [ТС]     Объясните ситуацию с integer, float и double. Выводится число на единицу меньше положенного #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 а его не выводит! сейчас разберусь
zss
Модератор
Эксперт С++
 Аватар для zss
5946 / 5551 / 1784
Регистрация: 18.12.2011
Сообщений: 14,181
Завершенные тесты: 1
17.03.2014, 16:00     Объясните ситуацию с integer, float и double. Выводится число на единицу меньше положенного #5
Соображение простые.
поскольку num_sq имеет тип float, то
выполняются следующие действия
C++
1
num_sq = num_sq / 10;
1. Преобразование num_sq в double
2. Преобразование 10 в double
3. Деление
4. Преобразование во float
Это повторяется в цикле.
В результате и накапливается ошибка округления.
VisualNIK
 Аватар для VisualNIK
8 / 8 / 1
Регистрация: 29.10.2012
Сообщений: 168
17.03.2014, 17:58  [ТС]     Объясните ситуацию с integer, float и double. Выводится число на единицу меньше положенного #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, в таком случае потери точности быть не должно?
DrOffset
6442 / 3816 / 885
Регистрация: 30.01.2014
Сообщений: 6,610
17.03.2014, 18:32     Объясните ситуацию с integer, float и double. Выводится число на единицу меньше положенного #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. И все.
zss
Модератор
Эксперт С++
 Аватар для zss
5946 / 5551 / 1784
Регистрация: 18.12.2011
Сообщений: 14,181
Завершенные тесты: 1
17.03.2014, 19:11     Объясните ситуацию с integer, float и double. Выводится число на единицу меньше положенного #8
Цитата Сообщение от DrOffset Посмотреть сообщение
С чего бы вдруг?
Я имею ввиду, что процессор ПК работает с числами double.
Поэтому float приходится преобразовывать в double
(а уж int (десятку) тем более).
Для мобильных процессоров это скорее всего не так.
DrOffset
6442 / 3816 / 885
Регистрация: 30.01.2014
Сообщений: 6,610
17.03.2014, 21:12     Объясните ситуацию с integer, float и double. Выводится число на единицу меньше положенного #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
Никаких преобразований тут нет.
Tulosba
:)
Эксперт С++
4378 / 3221 / 297
Регистрация: 19.02.2013
Сообщений: 9,044
17.03.2014, 22:03     Объясните ситуацию с integer, float и double. Выводится число на единицу меньше положенного #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
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
18.03.2014, 05:18     Объясните ситуацию с integer, float и double. Выводится число на единицу меньше положенного
Еще ссылки по теме:

C++ Если целое число М делится на целое число N, то на экран выводится частное от деления, в противном случае выводится сообщение
C++ Как проверить вводилось ли число (типа double или float) в консоль
Преобразовать 2 числа int в 1 число float(double) | double int1.int2 C++

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

Или воспользуйтесь поиском по форуму:
VisualNIK
 Аватар для VisualNIK
8 / 8 / 1
Регистрация: 29.10.2012
Сообщений: 168
18.03.2014, 05:18  [ТС]     Объясните ситуацию с integer, float и double. Выводится число на единицу меньше положенного #11
Tulosba, тут на математике просто завязали.. Спасибо нужно же уметь мыслить не только в глубь н и в ширь...тоже инетерсный вариант....а static_cast<int> это типа преобразование в int, что-то вроде int(log10(n)), я правильно понял?
Yandex
Объявления
18.03.2014, 05:18     Объясните ситуацию с integer, float и double. Выводится число на единицу меньше положенного
Ответ Создать тему
Опции темы

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