Максимальное число
В твоём случае ты ответил на свой вопрос. 15 знаков.
Читай как строку и/или использую библиотеки, которые позволяют работать с числами с произвольной точностью.
а это как ещё? какие есть библиотеки для этого?
а на чём пишешь-то?
С++ (visual)
У long double - 21 знак верный
с разной плотностью - около нуля погуще, около единицы - пореже, около тысячи - ещё больше расстояния между соседними числами.
мышинным эпсилон называется расстояние между соседними числами около единицы.
для double это примерно 1e-16, для long double 1e-21, для float 1e-6
чтобы выяснить расстояние между числами около некоторого числа X, надо эпсилон умножить на это самое X.
т.е. около миллиона для float расстояние равно X*float_eps=1e6*1e-6=1. (примерно)
т.е. с точки зрения машины 1'000'000.0 и 1'000'000.5 неразличимы (для типа float)
расстояние между числами около нуля - 1e-308 (double)
И машина вполне себе нормально считает числа порядка 1e200 - складывает, умножает. тут только надо себе отчёт отдавать в том, сколько знаков мы имеем.
GMP если тебе нужна большая точность.
Используй
Это просто Макаров-Землянский прикалывается, просит чтобы ему в виде %30.30f выводило, а машина по этому поводу ерунду выдает....и никак не сдать ему задачку..
Что б ты ему объяснил, что так не бывает.
до пятница все равно разберусь (придется) =)
Даже был такой случай: я сидела в 13-08 а он у кого-то прогу принимал со словами "а ща я покажу, как нужно делать, чтобы прога зависла и не работала..гыгы"...
Сорри. Ошибся с полом
eps=1.110223e-16 и для double, float, long double. почему так?
"Ай-яй-яй" другое говорит.
---
...Я работаю антинаучным аферистом...
#include <math.h>
double eps;
void main
{
eps=1.;
while 1.+eps)>1)
{
eps/=2;
}
printf("eps=%.10le\n",eps);
}
вот оно
#include <stdio.h>
#include <math.h>
typedef float mytype;
mytype eps,one,tmp;
void main
{
eps=1.;
one=1.;
tmp=one+eps;
while (tmp>one)
{
eps/=2;
tmp=one+eps;
}
printf("eps=%g\n",eps);
}
long double на MSVS 7.0 почему-то кажет тот же результат, что и дабл.
на gcc всё пучком
Опять же, это не очень-то нуль.
Или подразумевалась именно наименьшая достижимая относительная
погрешность?
---
...Я работаю антинаучным аферистом...
Простой пример:
#include <math.h>
int main
{
int i=0;
double a=0;
double eps=1, eps1;
while(a != (double)1.0) {
eps /= (double)2.0;
a += eps;
i++;
}
printf("eps+ = %le, i=%d\n", eps, i);
i=0;
a=(double)1.0;
eps = 1;
while(a != (double)0.0 && eps != (double)0.0) {
eps1 = eps;
eps /= (double)2.0;
a -= eps;
i++;
}
printf("eps- = %le, i=%d\n", eps1, i);
return 0;
}
для gcc, double получаем
eps+ = 5.551115e-17, i=54
eps- = 4.940656e-324, i=1075
"Ай-яй-яй," но ты неправ.
---
...Я работаю антинаучным аферистом...
но ты неправ.
В чем именно я не прав? Ты действительно считаешь, что компьютерная точность вычислений не зависит от постановки вычислений?
у меня gcc на три типа выдаёт разные результаты - порядка 1e-8, 1e-16, 1e-22
постановка задачи была - посчитать (оценить порядок) расстояние между числами в окрестности единицы.
я считаю, приведённая программа с этой задачей справилась.
способа вычислений.
---
...Я работаю антинаучным аферистом...
long double на MSVS 7.0 почему-то кажет тот же результат, что и дабл.
(Я этого не делал, но думаю что можно даже догадаться почему, если поглядеть в ассемблерный листинг программы
fc: no differences encountered
...а что касается подключить библиотеку, то как я это сделаю в комп классе? и я про то..
в любом случае, всем спасибо..
Маза у MS long double 8-байтовый
Но если перейти к конкретной прикладной задаче - вычисления на C на x86, то точность результата от постановки вычислений зависит. Существует достаточно классический пример (программу для иллюстрации лень писать):
Будем вычислять значение функции разложением в ряд. Возьмем достаточное количество членов ряда, чтобы наверняка превысить компьютерную точность, и посчитаем две суммы: одну начиная суммирование с больших членов ряда к меньшим, а вторую - наоборот, от меньших членов к большим. Результаты будут различаться.
И чем же я не прав?
постановка задачи была - посчитать (оценить порядок) расстояние между числами в окрестности единицы.
я считаю, приведённая программа с этой задачей справилась.
приведенный мной пример тоже считает точность в окрестностях единицы. Только первая точность получается в окрестностях единицы, если к ней приближаться со стороны 0, а вторая - если приближаться со стороны +oo. Результаты различаются. Зависят от постановки вычислений.
первый цикл действительно считает что-то в районе 1
но второй то в районе нуля...
Поэтому такая разительная разница... .940656e-324
324-16=308 точность предсказанная базилио
вот нафлудили-то, я ещё больше запуталась....
Держи правильный подсчет при приближении от 0 и приближении от 2. Результаты получишь разные, конечно не 1e-324 как у 0, но один порядок разницы все равно есть:
#include <math.h>
int main
{
int i=0;
double a=0;
double eps=1, eps1;
while(a != (double)1.0) {
eps /= (double)2.0;
a += eps;
i++;
}
printf("eps+ = %le, i=%d\n", eps, i);
i=0;
a=(double)2.0;
eps = 1;
while(a != (double)1.0 && eps != (double)0.0) {
eps1 = eps;
eps /= (double)2.0;
a -= eps;
i++;
}
printf("eps- = %le, i=%d\n", eps1, i);
return 0;
}
eps+ = 5.551115e-017, i=54
eps- = 2.220446e-016, i=53
определение машинного нуля: минимально возможное eps, для котор верно eps+1>1
Корявое определение. Чем хуже минимальное eps', для которого верно 1-eps' < 1?
Для справки, eps != eps'.
С чего бы это вдруг...
Console.WriteLine(float.Epsilon.ToString + " " + double.Epsilon.ToString;
1.401298E-45 4.94065645841247E-324
C# вполне удовлетворяет IEEE 754, так что епсилоны ДОЛЖНЫ быть такими.
2Лео: что за херня, причем тут точность вычислений?
Флоат состоит из одного байта экспоненты, одного бита знака и 23 битов мантиссы. Чтобы из этого всего получить число, например, в десятичной системе счисления следует:
1) дописать к мантиссе слева двоичную единичку и перевести ее в десятичную систему счисления.
2) умножить мантиссу на 2^экспонента, воспринимая экспоненту как число от -128 до 127. Хотя тут уже хз, мб из нее еще что-нить вычесть надо, но это совершенно не важно.
3) в зависимости от бита знака умножить результат на +1 или -1.
Все!
Соответственно, можно поставить вопрос: какое ближайшее к нулю положительное число можно записать флоатом. Ответ выше. Кстати, положительные и отрицательные числа симметричны.
Еще можно поставить вопрос, какое ближайшее к 1 положительное число большее 1 можно записать флоатом. Вроде как должно получится 1 + 2^(-23) или 1 + 2^(-24).
Забавно. В VS2003 тоже никаких различий.
{
int i = Magick_Constant;
float f;
f = *float*)&i);
printf("%f", f);
}
А дальше в течение пятнадцати минут при помощи Магической Константы полностью определяется формат флоата. А заодно и все возможные эпсилоны, которые только могут придти в голову.
Кстати, надо еще учитывать, что некоторые комбинации зарезервированны под nan и +-inf.
Еще можно поставить вопрос, какое ближайшее к 1 положительное число большее 1 можно записать флоатом. Вроде как должно получится 1 + 2^(-23) или 1 + 2^(-24).
Ответ на вопрос какое ближайшее к X положительное число можно записать флоатом не равен тому, что ты написал. Ответ на этот вопрос очень сильно зависит от X. Если ты аккуратно запишешь действия, которые нужны для сложения двух чисел с разными мантиссами, то с удивлением обнаружишь, что число 1+2^(-23) неотличимо от числа 1.
А число 100 неотличимо от числа 100 + 1e-14. А число 10000 неотличимо от 10000 + 1-12. И так далее.
Просто ты, как и многие, путаешь минимальное число, отличимое от 0 (безусловно, равное float.Epsilon в терминах C# и минимальное число, отличимое от X.
Это тебе в подспорье, для проверки таких гипотез на языке C#, соответствующем стандарту IEEE 754.
using System;
namespace Epsilon
{
class Eps
{
[STAThread]
static void Main(string[] args)
{
float eps1, eps;
float x = 1.0F;
eps1 = eps = 1.0F;
while(eps != (float)0.0 && x+eps>x)
{
eps1 = eps;
eps /= (float)2.0;
}
Console.WriteLine("eps+ = " + eps1);
eps1 = eps = 1.0F;
while(eps != (float)0.0 && x-eps<x)
{
eps1 = eps;
eps /= (float)2.0;
}
Console.WriteLine("eps- = " + eps1);
}
}
}
Ты не понимаешь сути проблемы. Внимательно прочитай , специально для тебя сейчас выделю жирным важный момент.
eps с предыдущего шага, если бы ты это делал в первом случа то выводимые числа сравнялись, а так
этот эффект удобнее наблюдать на другой программе
#include <math.h>
int main{
int i=0;
double a=0;
double eps=1, eps1;
eps=1;
for(i=1;i<100;i++){
eps /= (double)2.0;
printf(" %d= %le, %d!",i,epsdouble)1.0) != double)1.0 - eps) + (eps/(double)2.0;
printf(" %d\n"double)1.0) != double)1.0 + eps) - (eps/(double)2.0;
}
return 0;
}
в первом принтфе 1 не получается дольше.
ЗЫ Кстати я не очень понимаю почему работает твоя программа, если делать в уме, то единица там не должна получиться по крайней мере
во втором случае. Возможно я просто не понимаю округлений при действиях.
Проблема там не в округлениях при действиях, а в сравнении чисел с разной мантиссой. Это вносит свои ограничения. Если поискать eps в районе 0 и в районе 1e10, то его отличие от результатата для 1 может сильно впечатлить.
какое ближайшее к 1 положительное число большее 1 можно записать флоатомДружок! Где ты в вышеприведенной цытате увидел букву Х?
Просто ты, как и многие, путаешь минимальное число, отличимое от 0 (безусловно, равное float.Epsilon в терминах C# и минимальное число, отличимое от X.Просто ты, как и многие, невнимательно читаешь чужие посты. Да и вообще немного туповат.
float one = 1;
float eps = (float)Math.Pow(2, -24);
float onemore1 = one + eps;
float delta1 = onemore1 - one;
float onemore2 = one + eps*1.01f;
float delta2 = onemore2 - one;
float onemore3 = one + eps*0.99f;
float delta3 = onemore3 - one;
Console.WriteLine("{0:F10} {1:F10} {2:F10} {3:F10}", onemore1, onemore2, onemore3, eps);
Console.WriteLine("{0:F10} {1:F10} {2:F10}", delta1, delta2, delta3);
1,0000000000 1,0000000000 1,0000000000 0,0000000596Такой изврат понадобился от того, что врайтлайн отрубает последний десятичный знак.
0,0000000000 0,0000001192 0,0000000000
Итак, как мы видим моя гипотеза о 1 + 10(-24) (или -23, хз как там с округлением) гениально подтвердилась.
2Шурик: видишь ли, на иеее документация платная, а искать ее в другом месте было влом. Особенно что там дохуя говна, наверное, а тут такой тривиальный вопрос.
1.111...11e1==1.0e0 в двоичной записи
либо добавление 1/2^n в какой-то
момент округляет первое число до 1
либо сравнение ведется с точностью до
какой-то констатнты заведомо больше
машинного eps, тогда твои и базилио расчеты неверны -
надо добавлять предполагаемый eps много раз
(а именно 2^ (разница между степенью eps и степенью округления сравнения чтобы
убедиться что ничего не добавляется
Оставить комментарий
Marina11
Такой вопрос возник..есть ну так сказать " машинный ноль" только в обратную сторону, т.е. максимальное число, котор машина может считать (ответ : для double 1.7e-308...1.7e+308 не рассматривается)? Просто возникла такая проблема, что машина читает из файла число с 30ю знаками, но из них только первые 15 верны, а дальше какие-то др числа ставит.. типа не получается у неё такое большое число прочитать...