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

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Десятичная дробь - не понятки... лучше загляни чтоб понять :) 
:(
    Опции темы
W4FhLF
Дата 20.12.2006, 08:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


found myself
****


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

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



Код

если ты про double тот там тот-же исход, разве что в некоторых случаях слегка другой..


Тут ещё зависит от разрядности целой части, double является длинным форматом представления float point чисел, где под мантиссу или дробную часть числа отводится 53 байта, что при нулевом значении целой части может дать точность до 16 знаков после запятой.


--------------------
"Бог умер" © Ницше
"Ницше умер" © Бог
PM ICQ   Вверх
ressac
Дата 23.12.2006, 00:34 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



я вернусь к старому , к тому с чего и начал, проблему которую я тут запостил можно разрешить по старинке просто с for'ом? без char'ов и подобных вещей. просто один FOR.
PM MAIL   Вверх
Anikmar
Дата 23.12.2006, 00:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2513
Регистрация: 26.11.2006
Где: Санкт-Петербург

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



На мой взгляд нельзя.
Когда ты вводишь цифры с клавиатуры - ты вводишь все равно char, что бы там не говорили.

ты вводишь 0.01 - это символы.

потом среда (программа) преобразует эти цифры в float. Бинарная точность float далеко не всегда совпадает с десятичной. Если ты ввел 0.01 - программа пытается преобразовать это во float с максимальной точностью. получается (это только пример) некое число в формате float. Оно может вглыдеть как 0.009999999999999999999999999999999999.
Если воспользоваться твоим алгоритомом - получишь результат, который ты уже видел.

Следовательно - чисто математическими методами здесь никак не обойтись - все равно будет погрешность.

Резюме:
Я бы задал некоторую точность: допустим программа работает с числами, которые не превышают 10 знаков после запятой. Тогда можно введенное число округлить до этой точности, а потом воспользоваться твоим алгоритмом. 

Я бы использовал метод:
Допустим ввели 120344.04563

Сначала - привел бы число к значению меньше 1 (последовательным делением на 10)
Получил бы результат 0.04563

Потом умножил бы на 10000000000 (до кличества знаков) - это уже можно делать в типе long int
В результате получил бы число
456300000
Дальше можно по алгоритму - с целыми числами он сработает (при некой модификации)

Моя мысля должна работать до предела знаков после запятой, равной длине (long) int...

Если ошибся - не бейте.

PM MAIL ICQ   Вверх
ressac
Дата 23.12.2006, 01:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



ты не ошибся вроде бы всё хорошо,только с нулями в конце что будем делать? (я не совсем понял этот момент).

PM MAIL   Вверх
Anikmar
Дата 23.12.2006, 10:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2513
Регистрация: 26.11.2006
Где: Санкт-Петербург

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



Незначащие конечные нули - выбрасываем.

Наверное надо сделать цикл вроде
Код

int a = 456300000;
// Это наша дробная часть
while (((a%10) == 0)&&(a>0))
{
   a/= 10; // Пока делится на 10 без остатка - отбрасываем незначащие нули
}

// Теперь a состоит только из значащих цифр - действуем по алгоритму
int Count = 0; // Были только одни нули - количество цифр после запятой 0
while (a>=1)
{
  a /= 10;
  Count ++;
}
// Count - количество знаков после запятой


Что-то в этом роде

Видимо не проснулся - немного подправил

Это сообщение отредактировал(а) Anikmar - 23.12.2006, 10:19
PM MAIL ICQ   Вверх
Dov
Дата 23.12.2006, 11:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


аСинизатор
***


Профиль
Группа: Завсегдатай
Сообщений: 1721
Регистрация: 10.5.2003
Где: Эрец-Исраэль

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



Цитата(Anikmar @  22.12.2006,  23:59 Найти цитируемый пост)
Получил бы результат 0.04563
...
Цитата(Anikmar @  22.12.2006,  23:59 Найти цитируемый пост)
В результате получил бы число456300000
...
Цитата(Anikmar @  23.12.2006,  09:16 Найти цитируемый пост)
// Count - количество знаков после запятой
...

По-моему, чего-то не того. 5 != 4.  smile 



--------------------
Тут вечности запах томительный,
И свежие фрукты дешевые, 
А климат у нас – изумительный, 
И только соседи – #уевые. 
                           Игорь Губерман.
PM   Вверх
ressac
Дата 23.12.2006, 11:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



хорошо только ведь этот блок будет отбирать и нужные нам нули , понимаешь о чём я говорю? 


Код

while (((a%10) == 0)&&(a>0))
{
   a/= 10; // Пока делится на 10 без остатка - отбрасываем незначащие нули
}


тойсть было "0,02" умножили на 100....... получили двойку в конце с кучей нолей и затем их убрали и один нужный нолик нам мы потеряли, в принципе можно совместить твой и мой алгоритм, мой будет считать сколько нолей до первой цифры (это у него получается вроде-бы если я не ошибаюсь) а твой затем будет переносить их на левую часть дроби и считать цифры, вроде должно пройти, но минус есть серовно, максимальное чилсо будет состоять из 10 цифр, ну это лучше чем ничего всё таки


2Dov

я не понял о чём ты. или ты о том-же о чём и я? smile
PM MAIL   Вверх
Anikmar
Дата 23.12.2006, 12:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2513
Регистрация: 26.11.2006
Где: Санкт-Петербург

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



На самом деле - если работать чисто с числами там все равно будет куча цифр, которые пользователь не вводил.
Число 56.0475 будет представлено как 56.047499999999999999999999999

Так что все-таки проще разобрать введенную строку и посчитать количество знаков после запятой. Конечные нули можно и обрезать.
Это будет наипростейший и самый правильный выход.

А так, в большинстве случаев будет выдаваться результат, совпадающий с заданной точностью.
PM MAIL ICQ   Вверх
Dov
Дата 23.12.2006, 12:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


аСинизатор
***


Профиль
Группа: Завсегдатай
Сообщений: 1721
Регистрация: 10.5.2003
Где: Эрец-Исраэль

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



Цитата(ressac @  23.12.2006,  10:55 Найти цитируемый пост)
2Dov я не понял о чём ты. или ты о том-же о чём и я? 

ressac, я о том, что нужный ноль был утерян не после того, как получили двойку в конце с кучей нолей и затем их убрали, а  после того, как умножили на 100.


--------------------
Тут вечности запах томительный,
И свежие фрукты дешевые, 
А климат у нас – изумительный, 
И только соседи – #уевые. 
                           Игорь Губерман.
PM   Вверх
Rockie
Дата 23.12.2006, 14:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1143
Регистрация: 23.4.2006

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



Цитата(Anikmar @  23.12.2006,  00:59 Найти цитируемый пост)
Когда ты вводишь цифры с клавиатуры - ты вводишь все равно char, что бы там не говорили.ты вводишь 0.01 - это символы.потом среда (программа) преобразует эти цифры в float.

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





--------------------
Чтобы иметь большой гардероб - надо иметь большой гардероб.
PM   Вверх
Anikmar
Дата 23.12.2006, 15:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2513
Регистрация: 26.11.2006
Где: Санкт-Петербург

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



Цитата(Rockie @  23.12.2006,  14:27 Найти цитируемый пост)
Вводишь пиксели а они потом там, по проводочкам, преобразуются 


Ну если быть совсем точным, то при нажатии клавиши формируется прерывание 09, обработчик прерывания считывает SCAN-код клавиши, и помещает его в буффер 
Драйвер клавиатуры считывает из буфера этот скан-код, преобразовывает его в код клавиши и отправляет в буфер нажатых клавиш.

Винда берет этот код, посылает активному окну сообщение о нажатии клавиши.

Соответственно обработчик данного сообщения берет код нажатой клавиши и помещает его в сандартный поток ввода.

Несколько упрощенно, но где-то так.

Так вот: в стандартный поток ввода помещается char!  smile  smile 
PM MAIL ICQ   Вверх
Rockie
Дата 23.12.2006, 16:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1143
Регистрация: 23.4.2006

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



Цитата(Anikmar @  23.12.2006,  15:04 Найти цитируемый пост)
Так вот: в стандартный поток ввода помещается char!  smile  smile  


Anikmar, то есть я сейчас char считал?
Код
double i;
cin>>i;


Цитата(Anikmar @  23.12.2006,  00:59 Найти цитируемый пост)
Когда ты вводишь цифры с клавиатуры - ты вводишь все равно char, что бы там не говорили.

А если я Ctrl+Alt+Del жмакаю я какой char ввожу?.. 

Клавиатура здесь вообще не при чем, это не единственный способ ввести число.




--------------------
Чтобы иметь большой гардероб - надо иметь большой гардероб.
PM   Вверх
ressac
  Дата 23.12.2006, 20:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



силь больше нет думать smile
погрешности при вычислениях есть и будут...
у кого-то есть идеи получше ?


Код

#include <stdio.h>

main()
{
 int i=1,digits=-1; unsigned long num_w2=0; double num_w,num_f,num_fb;

 printf("Enter the number: ");scanf("%lf",&num_f);
 num_w=num_f;

  //считаем нули после запятой до любого числа ( кроме нуля естествено :) )
  for(;!num_w2;num_w*=10,num_w2=num_w,num_w-=num_w2,digits++)
  {
   if(!num_w2) num_fb=num_w;
   printf("\nS4itaem nuli posle zapyatoy: %lf\n",num_w);
   //system("pause");
  }

  printf("\nNuley posle zaptatoy: %d\n",digits);

  num_w2=num_fb*10e8;
  printf("\nLong int: %d\n",num_w2);

  //убираем нули 
  for(;!(num_w2%10);num_w2/=10)
  {
   printf("\nUberaem nuli: %d\n",num_w2);
   //system("pause");
  }

  //убираем девятки
  for(;num_w2%10==9;num_w2/=10)
  {
   printf("\nUberaem devyatki: %d\n",num_w2);
   //system("pause");
  }

  //считаем то что у нас осталось после всех фильтров
  for(;num_w2;num_w2/=10,digits++)
  {
   printf("\nS4itaem cifri: %d\n",num_w2);
   //system("pause");
  }

  if(num_f==0.9) digits=1; //на тот случай если 0.9

 //и сколько всего цифр у нас :)...
 printf("\nDigits final: %d\n",digits);
system("pause");
}

PM MAIL   Вверх
Anikmar
Дата 23.12.2006, 22:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2513
Регистрация: 26.11.2006
Где: Санкт-Петербург

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



Цитата(Rockie @  23.12.2006,  16:37 Найти цитируемый пост)
Anikmar, то есть я сейчас char считал?

код C++
1:
2:

double i;
cin>>i;


Ну вообще-то я в шутку писал  smile В любом случае с клавиатуры ты вводишь те символы, которые нарисованы на кнопках, служебные отрабатываются по-особому, это не суть. Если ты вводишь последовательность символов 123, то с точки зрения клавиатуры - ты ввел три символа, а с точки зрения программы - это может быть и char и byte и int и string и float - смотря какого типа переменную поставишь. Но набрал ты 123 - так что это по-твоему? Число? Строка? Код символа? - Естественно это просто 3 символа. С кодами 49, 50 и 51. Во что их преобразует конкретная программа - это от программиста зависит.

Но на самом деле, если серьезно, когда ты вводишь с клавиатуры символы 345.04567, которые преобрразуются в double, а потом в отладчике посмотришь чему этот double равен - ты увидишь немного отличающееся значение. Это и есть погрешность преобразования десятичного числа в двоичное (коим double собственно и является).

Если в задаче стоит посчитать количество знаков после запятой в десятичном числе - нужно воспользоваться строковым выражением - т.е. преобразовать число в строку с заданным параметром округления.

Если число вводится с клавиатуры - надо сразу его обрабатывать как строку.
Если число формируется программно - точного результата достичь не получится - с этим ничего нельзя сделать, особенности архитектуры.

Тут можно использовать не двоичную систему - а прямую трансляцию десятичной в двоичную (точно не помню, по-моему такое называется BCD, но не уверен). Но в рамках поставленной задачи не уверен, что это необходимо.

PM MAIL ICQ   Вверх
ressac
Дата 24.12.2006, 04:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



а можно-ли одновремено сохранить число в строку(чар) и в перменую? в том момент когда мы вводим его? 
PM MAIL   Вверх
Страницы: (3) Все 1 [2] 3 
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
Earnest Daevaorn

Добро пожаловать!

  • Черновик стандарта C++ (за октябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика(4.4мб).
  • Черновик стандарта C (за сентябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика (3.4мб).
  • Прежде чем задать вопрос, прочтите это и/или это!
  • Здесь хранится весь мировой запас ссылок на документы, связанные с C++ :)
  • Не брезгуйте пользоваться тегами [code=cpp][/code].
  • Пожалуйста, не просите написать за вас программы в этом разделе - для этого существует "Центр Помощи".
  • C++ FAQ

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

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


 




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


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

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