|
Olegator
|
|
« Ответ #1 : 20-12-2004 19:03 » |
|
С помощью цикла с постусловием делишь на 10.0 до тех пор пока число не станет < 1.
double n; do n=n/10.0; while (n>=1); printf("%lf",n)
|
|
|
Записан
|
|
|
|
|
nikedeforest
|
|
« Ответ #3 : 20-12-2004 22:06 » |
|
Вот может такая идейка подойдет, код конечно можно оптимизировать, это на скорую руку, также можно менять коэффициент но которе происходит сдвиг (самое главное-это смысл ) #include <stdio.h> #include <conio.h> void main () { clrscr(); double point; double koef=10,s=1; printf("input point"); scanf("%lf",&point);
do { s=1; if(point<0.1) { for(int i=0; point<0.1;i++,s*=10) {point*=koef*s;} } ////////////// s=1; if(point>1) { for(int i=0; point>1;i++,s*=100) {point/=koef*s;} } } while(!(point<1&&point>0.1)); cout<<"\n"<<point; return; }
Выводит число не целиком, но на самом деле, там то что надо, в инспекторе можешь посмотреть.
|
|
« Последнее редактирование: 03-12-2007 17:24 от Алексей1153++ »
|
Записан
|
ещё один вопрос ...
|
|
|
Alf
Гость
|
|
« Ответ #4 : 20-12-2004 22:33 » |
|
Если можно пользоваться операциями взятия логарифма и возведения в степень, без которых вряд ли обходится любая библиотека стандартных математических функций, то решить подобную задачу несложно.
В данном примере:
1. Берем исходное число - 123781344664681 2. Вычисляем его логарифм по основанию 10: Log10(123781344664681) = 14.09265519622138561074672569222 (разумеется, такая точность здесь излишня, я просто копирую результат из штатного калькулятора Windows). 3. Берем целую часть логарифма (14) и прибавляем 1, получаем 15. 4. Делим исходное число на 10 в степени 15, получаем: 123781344664681/(10^15) = 0.123781344664681
В общем случае, если исходное число X, искомое число Y определяется формулой:
Y = X / (10 ^ (INT(LOG10(X)) + 1)), где ^ - операция возведения в степень, INT - функция взятия целой части числа, LOG10 - логарифм числа по основанию 10.
Поскольку компы без математического сопроцессора уже канули в Лету, думаю, такая конструкция будет работать поэффективнее деления в цикле при достаточно большом значении X.
|
|
|
Записан
|
|
|
|
LEON
Гость
|
|
« Ответ #5 : 21-12-2004 10:42 » |
|
А если число перевести в строку, слева дописать 0. и обратно в double?
|
|
|
Записан
|
|
|
|
nikedeforest
|
|
« Ответ #6 : 21-12-2004 14:25 » |
|
Из double в string(Delphi) или в char (С) перевести нельзя.
|
|
|
Записан
|
ещё один вопрос ...
|
|
|
nikedeforest
|
|
« Ответ #7 : 21-12-2004 14:26 » |
|
Из double в string(Delphi) или в char (С) перевести нельзя.
|
|
|
Записан
|
ещё один вопрос ...
|
|
|
Alf
Гость
|
|
« Ответ #8 : 21-12-2004 14:56 » |
|
Из double в string(Delphi) или в char (С) перевести нельзя.
Посредством sprintf можно. Только очень сомнительно, что окажется эффективнее вычисления логарифма при большом количестве значащих цифр.
|
|
|
Записан
|
|
|
|
nikedeforest
|
|
« Ответ #9 : 21-12-2004 15:32 » |
|
На сколько я помню, функция printf выводит числа ограниченной длины, там не больше 6 символов, если я не ошибаюсь. Интересно, на sprintf такие ограничения распространяются
|
|
|
Записан
|
ещё один вопрос ...
|
|
|
npak
|
|
« Ответ #10 : 21-12-2004 15:54 » |
|
на печать выводится любое количество знаков, это можно настроить в строке формата.
Непонятно другое -- что делать с этим дальше? Ну получится строка "1,234567890123456e+78", и что? надо разбирать строку, выделять мантиссу и показатель, потом мантиссу переводить в число. Но при этом число изменится -- либо часть знаков потеряется из-за недостаточной точности, либо новые получатся, если точность печати превышает точность мантиссы. нехорошо и то, и другое.
Я думаю, что десятичный логарифм -- наиболее подходящее решение.
|
|
|
Записан
|
|
|
|
Mfcer__
Команда клуба
Offline
|
|
« Ответ #11 : 21-12-2004 23:52 » |
|
double a = 12812896757; int po = ((int)log10(a)) +1; cout << po << endl; double val = pow(10,po); cout << val << endl; printf("%lf",a/val); a /= val; if ( a == 0.12812896757 ) // это условие не срабатывает, а на экран выводиться всякий бред... cout << "Asasfaf" << endl;
|
|
|
Записан
|
|
|
|
maa
|
|
« Ответ #12 : 22-12-2004 04:31 » |
|
У меня твой код великолепно отработал. Компилятор - Visual C++ 6.0. Добавил только инклюды и main () {...}
#include <math.h> #include <iostream.h> #include <stdio.h>
|
|
« Последнее редактирование: 22-12-2004 04:33 от maa »
|
Записан
|
|
|
|
Alf
Гость
|
|
« Ответ #13 : 22-12-2004 07:50 » |
|
... if ( a == 0.12812896757 ) // это условие не срабатывает, а на экран выводиться всякий бред... cout << "Asasfaf" << endl; Выбрось это условие и поставь вместо него безусловную печать значения a. Ни в коем случае нельзя сравнивать величины типа double и float на равенство, а тем более с литеральной константой.
|
|
|
Записан
|
|
|
|
PSD
Главный специалист
Offline
Пол:
|
|
« Ответ #14 : 22-12-2004 08:31 » |
|
А идея просто забить эхпоненту нулями не подходит?
|
|
« Последнее редактирование: 22-12-2004 08:34 от PSD »
|
Записан
|
Да да нет нет все остальное от лукавого.
|
|
|
Mfcer__
Команда клуба
Offline
|
|
« Ответ #15 : 22-12-2004 11:06 » |
|
А идея просто забить эхпоненту нулями не подходит?
Это как ? Можно поподробнее...
|
|
|
Записан
|
|
|
|
PSD
Главный специалист
Offline
Пол:
|
|
« Ответ #16 : 22-12-2004 12:18 » |
|
Точно не скажу но из курса ПТЦА помню что числа сплавующей точкой хранятся в формате +|Мантиса|+|экспанента (в каком порядке они лежат в double не знаю, поищи в MSDN) Причем мантиса всегда хранится в нормализованом виде те 0.123456 если эти правила дествуют и для типа double то для того чтобы из 12323456787 получить 0.12323456787 достаточно зделать экспаненту раной 1.Для формата double это заменить 12 бит на константу. Только я не уверен что число там нормализованное...
|
|
|
Записан
|
Да да нет нет все остальное от лукавого.
|
|
|
Pu
Большой босс
Offline
78
|
|
« Ответ #17 : 24-12-2004 08:24 » |
|
в каком порядке лежат написано и нарисовано очень понятно здесь - http://www.sibsutis.ru/~mavr/MP/cod.htm
|
|
|
Записан
|
Насколько я опытен? Достаточно, чтобы понимать, что дураков нельзя заставить думать по–другому, но недостаточно, чтобы отказаться от попыток это сделать. (с) Артур Джонс
|
|
|
pilpilon
Гость
|
|
« Ответ #18 : 25-12-2004 15:32 » |
|
#include <iostream> #include <iomanip> #include <sstream> using namespace std; string mant ( double); double input_double(); int main() { cout << "mant = " << mant(input_double()) << endl; return 0; } string mant ( double arg ) { ostringstream os; os <<" " << fixed << setprecision(24) << arg << endl; int pointpos = os.str().find('.'); os.seekp(0); os << "0."; return os.str().erase(pointpos,1).substr(0,26); } double input_double() { double arg = .0; cout << "enter double number" << endl; cin >> arg; return arg; } задаснка не столько про double , сколько про манипуляцию строками. А вот выгрызать мантиссу -- точно не будет работать нигде, кроме компьютера на котором скомпилировано ю
|
|
« Последнее редактирование: 20-12-2007 20:34 от Алексей1153++ »
|
Записан
|
|
|
|
PSD
Главный специалист
Offline
Пол:
|
|
« Ответ #19 : 27-12-2004 06:50 » |
|
задаснка не столько про double , сколько про манипуляцию строками. А вот выгрызать мантиссу -- точно не будет работать нигде, кроме компьютера на котором скомпилировано ю Обоснуй почему не будет работать? Я предпологал я то это должно работать как минимум на всем семействе 80х86!
|
|
|
Записан
|
Да да нет нет все остальное от лукавого.
|
|
|
pilpilon
Гость
|
|
« Ответ #20 : 27-12-2004 15:54 » |
|
Ты хочешь сказать, что длина <double> на машинах 80х86 никогда не менялась ? и не будет? и что формат <double> универсален для процессора, а не , например, операционной системы / компилятора ? что мантисса всегда нормализована?
Кроме того, в общем случае это не сильно эффективно. Ну есть у тебя число 12345678912345678. ну выгрыз ты его мантиссу ... получил, допустим, битовое представление числа 12345678912345678 ( допустм оно все в мантиссу влезло) - эту радость все равно надо хотя бы в < long> перевести, а еще потом делить...
|
|
|
Записан
|
|
|
|
PSD
Главный специалист
Offline
Пол:
|
|
« Ответ #21 : 28-12-2004 06:01 » |
|
Ты не прав в первом но прав во втором: По логике вещей тип добл обязан быть доинаков в рамках всего семества 80х86 как и все другие типы данных иначе старые программы просто бы не работали... первая констаната типа доубл похерела работу прораммы на камне использующем другой формат...
По второму вопросу ты прав я не учел что 9 и 0.9 имеют разню мантису....
|
|
|
Записан
|
Да да нет нет все остальное от лукавого.
|
|
|
baldr
|
|
« Ответ #22 : 28-12-2004 08:10 » |
|
Я уже не понимаю про что тут спор. Ноги растут из перевода в строку а потом обратно? Это ж бред. По-моему давным-давно Alf дал единственно верный и лучший вариант. За что ему плюс.
|
|
|
Записан
|
Приличный компьютер всегда будет стоить дороже 1000 долларов, потому что 500 долларов - это не вполне прилично
|
|
|
pilpilon
Гость
|
|
« Ответ #23 : 28-12-2004 13:22 » |
|
Зависит от того, что надо сделать с результатом. Если вывести на печать, то надо один раз перевести в строчку и дальше работать с ней - будет всяко быстрей. Если же от результата нужно взять арксинус -- другое дело. (Но тогда не важно, как число записывается, важно, чему оно примерно равно). Тут <Alf> все правильно написал, ( хотя как быстро вычисляться будет < val/pow(10.0 , ceil( log10( val ) ) ) > я судить не берусь, если повезет , то очень быстро, если нет - может и медленней, чем со строчкой.
Я в основном имел в виду , что в <C++> можно перевести <double> в <string>, причем так, как душе угодно, операция это эффективная и бояться ее не надо ( в тех случаях когда именно это и нужно)
|
|
|
Записан
|
|
|
|
|