Форум русскоязычного сообщества Ubuntu


Следите за новостями русскоязычного сообщества Ubuntu в Twitter-ленте @ubuntu_ru_loco

Автор Тема: Получение целой части числа  (Прочитано 2467 раз)

0 Пользователей и 1 Гость просматривают эту тему.

Оффлайн Гриб_под_зонтом

  • Автор темы
  • Активист
  • *
  • Сообщений: 301
    • Просмотр профиля
Получение целой части числа
« : 14 Июня 2015, 14:32:56 »
Здравствуйте, господа.
Сегодня опять наткнулся на удивительную математику в программировании, а именно: при получении целой части числа выводиться бред. Вот собственно код:
Код: (cpp) [Выделить]
#include <iostream>
#include <cmath>
#include <iomanip>
using namespace std;
int main()
{     
      long double A, B;
      int K;
      cin >> A >> B >> K;
      A = (A/B);
      cout << setprecision(40) << fixed << A << endl;
      A *= pow(10, K);
      cout << setprecision(40) << fixed << A << endl;
      K = int(A);
      cout << K << endl;
      K  %= 10;
      cout << K;
}
В нём на входе 3 числа, на выводе должно быть K цифра после запятой от деления A на B.
Вывод (с дебагом):
1 6 13
0.1666666666666666666711841757186896018084
1666666666666.6666667461395263671875000000000000000000
-2147483648
-8
Объясните пожалуйста
Hp 250 G3: 8Gb RAM, Intel Celeron 2.16-2.58GHz with 2 core, Intel HD Graphics.
Ubuntu 18.04 LTS with GNOME 3.

Оффлайн f-dzmitry

  • Участник
  • *
  • Сообщений: 168
    • Просмотр профиля
Re: Получение целой части числа
« Ответ #1 : 14 Июня 2015, 14:47:55 »
Ограничь. С начала.->По мне лучше си-ные функции. #include <cstdio>
« Последнее редактирование: 14 Июня 2015, 14:53:49 от f-dzmitry »
void next(){next();};

Оффлайн Гриб_под_зонтом

  • Автор темы
  • Активист
  • *
  • Сообщений: 301
    • Просмотр профиля
Re: Получение целой части числа
« Ответ #2 : 14 Июня 2015, 14:55:42 »
f-dzmitry,
K<10^9, как ограничить A/B?
Hp 250 G3: 8Gb RAM, Intel Celeron 2.16-2.58GHz with 2 core, Intel HD Graphics.
Ubuntu 18.04 LTS with GNOME 3.

Оффлайн alsoijw

  • Старожил
  • *
  • Сообщений: 4062
  • Fedora 25 GNOME 3 amd64
    • Просмотр профиля
Re: Получение целой части числа
« Ответ #3 : 14 Июня 2015, 15:59:19 »
f-dzmitry, что??
Гриб_под_зонтом, про a % b ты знаешь? Можно пример требуемой работы + то что вводишь?
Мало видеть нам начало - надо видеть и конец. Если видишь ты создание - значит где-то есть ТВОРЕЦ
Многие жалуются: геометрия в жизни не пригодилась. Ямб от хорея им приходится отличать ежедневно?

_Konstantin_

  • Гость
Re: Получение целой части числа
« Ответ #4 : 14 Июня 2015, 16:09:47 »
Здравствуйте, господа.
Сегодня опять наткнулся на удивительную математику в программировании, а именно: при получении целой части числа выводиться бред. Вот собственно код:
Код: (cpp) [Выделить]
#include <iostream>
#include <cmath>
#include <iomanip>
using namespace std;
int main()
{     
      long double A, B;
      int K;
      cin >> A >> B >> K;
      A = (A/B);
      cout << setprecision(40) << fixed << A << endl;
      A *= pow(10, K);
      cout << setprecision(40) << fixed << A << endl;
      K = int(A);
      cout << K << endl;
      K  %= 10;
      cout << K;
}
В нём на входе 3 числа, на выводе должно быть K цифра после запятой от деления A на B.
Вывод (с дебагом):
1 6 13
0.1666666666666666666711841757186896018084
1666666666666.6666667461395263671875000000000000000000
-2147483648
-8
Объясните пожалуйста
что то мне подсказывает, что все таки правильнее long double 1 https://msdn.microsoft.com/ru-ru/library/cc953fe1.aspx
но все равно не понимаю, ведь можно double, размер то ведь один и тот же - 8 байт...

Оффлайн Гриб_под_зонтом

  • Автор темы
  • Активист
  • *
  • Сообщений: 301
    • Просмотр профиля
Re: Получение целой части числа
« Ответ #5 : 14 Июня 2015, 16:35:39 »
alsoijw,
Например: ввожу 7 3 6, выводит 3.
Если именно ту часть , с которой ошибка, то на входе стоит например 3536473.4746453 на выходе 3536473
Hp 250 G3: 8Gb RAM, Intel Celeron 2.16-2.58GHz with 2 core, Intel HD Graphics.
Ubuntu 18.04 LTS with GNOME 3.

Оффлайн alsoijw

  • Старожил
  • *
  • Сообщений: 4062
  • Fedora 25 GNOME 3 amd64
    • Просмотр профиля
Re: Получение целой части числа
« Ответ #6 : 14 Июня 2015, 17:14:22 »
Гриб_под_зонтом, Формулы лучше всего сворачивать в одну строку. Вся часть с реальными
(Нажмите, чтобы показать/скрыть)
числами должна явно приводится в целое. Пример на vala
stdout.printf(((int)(a/b*Math.pow10(k))%10).to_string() + "\n");
Мало видеть нам начало - надо видеть и конец. Если видишь ты создание - значит где-то есть ТВОРЕЦ
Многие жалуются: геометрия в жизни не пригодилась. Ямб от хорея им приходится отличать ежедневно?

Оффлайн Гриб_под_зонтом

  • Автор темы
  • Активист
  • *
  • Сообщений: 301
    • Просмотр профиля
Re: Получение целой части числа
« Ответ #7 : 14 Июня 2015, 17:58:52 »
alsoijw,
Изначально всё было в одной строчке, я так сделал для того, что бы отоброзить промежуточные результаты
Hp 250 G3: 8Gb RAM, Intel Celeron 2.16-2.58GHz with 2 core, Intel HD Graphics.
Ubuntu 18.04 LTS with GNOME 3.

Оффлайн unimix

  • Активист
  • *
  • Сообщений: 537
    • Просмотр профиля
Re: Получение целой части числа
« Ответ #8 : 15 Июня 2015, 06:10:13 »
long double A;
int K;
K = int(A);
Сколько бит в int и какое макс. число туда можно записать?
Что такое и чем отличаются 'signed int' и 'unsigned int'?
Сколько будет в 'signed int' и 'unsigned int' если записать туда 0xffffffff?
Что такое приведение типов и "C-style Cast"?
« Последнее редактирование: 15 Июня 2015, 06:47:45 от unimix »

Оффлайн Гриб_под_зонтом

  • Автор темы
  • Активист
  • *
  • Сообщений: 301
    • Просмотр профиля
Re: Получение целой части числа
« Ответ #9 : 15 Июня 2015, 18:43:28 »
unimix,
1. int - 4 бита, диапазон : от -2 147 483 648 до 2 147 483 647.
2. signed - включая отрицательные числа, unsigned - только положительные.
3. Не знаю.
4. см. пункт 3.
Hp 250 G3: 8Gb RAM, Intel Celeron 2.16-2.58GHz with 2 core, Intel HD Graphics.
Ubuntu 18.04 LTS with GNOME 3.

_Konstantin_

  • Гость
Re: Получение целой части числа
« Ответ #10 : 15 Июня 2015, 18:57:32 »
unimix,
1. int - 4 бита, диапазон : от -2 147 483 648 до 2 147 483 647.
2. signed - включая отрицательные числа, unsigned - только положительные.
3. Не знаю.
4. см. пункт 3.
Вот этим советую пользоваться, пока не запомните:
https://msdn.microsoft.com/ru-ru/library/cc953fe1.aspx
https://msdn.microsoft.com/ru-ru/library/s3f49ktz.aspx

Оффлайн alsoijw

  • Старожил
  • *
  • Сообщений: 4062
  • Fedora 25 GNOME 3 amd64
    • Просмотр профиля
Re: Получение целой части числа
« Ответ #11 : 15 Июня 2015, 20:19:46 »
Гриб_под_зонтом, как не знаю?
Код: (cpp) [Выделить]
int a = 0xffffffff;
unsigned int b = 0xffffffff;
cout << a << ' ' << b << endl;
Цитировать
2. signed - включая отрицательные числа, unsigned - только положительные.
Ты же помнишь что в uint можно положить большее число?
Кстати да, длина int и максимальное число зависят от архитектуры.
« Последнее редактирование: 15 Июня 2015, 20:21:30 от alsoijw »
Мало видеть нам начало - надо видеть и конец. Если видишь ты создание - значит где-то есть ТВОРЕЦ
Многие жалуются: геометрия в жизни не пригодилась. Ямб от хорея им приходится отличать ежедневно?

Оффлайн unimix

  • Активист
  • *
  • Сообщений: 537
    • Просмотр профиля
Re: Получение целой части числа
« Ответ #12 : 15 Июня 2015, 20:30:40 »
1. int - 4 бита, диапазон : от -2 147 483 648 до 2 147 483 647.

В твоих условиях int = 32 бита (4 байта!), но может быть и иное.

Код: (cpp) [Выделить]
cout << K << endl;У тебя выводит -2 147 483 648

2. signed - включая отрицательные числа, unsigned - только положительные.

Изучи подробней. И 'signed', и 'unsigned' могут хранить 0xffffffff. Если коротко, то отличие их в использовании одного бита. Поэтому
Код: (cpp) [Выделить]
unsigned int Z1 = 0xffffffff; // Z1 = 4 294 967 295
signed int Z2 = 0xffffffff;   // Z2 = -1
unsigned int Z3 = 0x80000000; // Z3 = 2 147 483 648
signed int Z4 = 0x80000000;   // Z4 = -2 147 483 648

3. Не знаю.
4. см. пункт 3.

Изучи. Тогда не должно возникнуть вопросов, что можно ждать и как с приведением разных типов может получится неожиданный результат.
Скорее всего был использован  'static_cast' из 'long double' в 'int':
Код: (cpp) [Выделить]
long double A;
int K = static_cast<int>(A); // K = int(A);
« Последнее редактирование: 15 Июня 2015, 20:35:58 от unimix »

Оффлайн Гриб_под_зонтом

  • Автор темы
  • Активист
  • *
  • Сообщений: 301
    • Просмотр профиля
Re: Получение целой части числа
« Ответ #13 : 15 Июня 2015, 21:31:30 »
alsoijw,Конечно помню
_Konstantin_, этим и пользуюсь, а заодно и
(Нажмите, чтобы показать/скрыть)
Более-менее разобрался в чём дело. Неправильно переводит только в случае если K символ после запятой не был изменён при делении. Сам не знаю почему так, поэтому буду рад обьяснениям
Hp 250 G3: 8Gb RAM, Intel Celeron 2.16-2.58GHz with 2 core, Intel HD Graphics.
Ubuntu 18.04 LTS with GNOME 3.

Оффлайн unimix

  • Активист
  • *
  • Сообщений: 537
    • Просмотр профиля
Re: Получение целой части числа
« Ответ #14 : 16 Июня 2015, 00:44:16 »
Что-то непонятно, о каком изменении при делении.

Диапозон double = -9 223 372 036 854 775 808 .0   /   9 223 372 036 854 775 807.0
Диапозон int = -2 147 483 648   /   2 147 483 647
http://cppstudio.com/post/271/

Также непонятно, как ты собрался хранить в переменной int K значения больше  2 147 483 647.

Код: (cpp) [Выделить]
A = 1 / 6;        // A = 0.1666666666666666666711841757186896018084
A *= pow(10, 13); // A = 1666666666666.6666667461395263671875000000000000000000
K = int(A);       // 1 666 666 666 666 > 2 147 483 647

Исчисления происходят с double, вот и используй double K. Нужно округлить? Используй floor(A) или ceil(A). Но всё-равно таким способом не сможешь установить переменную K с помощью cin больше 18.
« Последнее редактирование: 16 Июня 2015, 00:46:31 от unimix »

 

Страница сгенерирована за 0.028 секунд. Запросов: 25.