LINUX.ORG.RU

LISP, C++, мультипере.. пара... А вот скажите лучше вот что!


0

0


Вчера в первый раз со времен автокада в институте решил попробовать лисп. Выбрал CLISP 2.33.1 и вот что увидел:

----------------------------

[1]> (- 2.45 2)
0.45000005
[2]>

----------------------------

Вот это дела! Ну и кого теперь мне нести на свалку то? AMD x86, kernel-2.6.10 или CLISP? Вопрос задаю серьезно, так как опечален таким исходом...

★★★★★

Ответ на: комментарий от anonymous

Я почему-то ожидал 0.45 ровно, без всяких довесков.

Только что пересчитал на нормальном бухгалтерском микрокалькуляторе с большими и удобными кнопками - 0.45. В столбик тоже получается 0.45.

plm ★★★★★
() автор топика

------------
  float a = 2.45;
  float b = 2.0;
  printf("%2.15f\n",a-b);
------------

 При компиляции с -O0 (чтоб они статически как double не посчитались) получаем 0.450000047683716

vsl
()
Ответ на: комментарий от vsl

Re: LISP, C++, мультипере.. пара... А вот скажите лучше вот что!
Хм, а у меня gcc насчитал 0.44(9) (по-видимому). Но вот так:

float res;
res = 2.45 - 2;
printf ("%.08f", res);

Хорошо хоть python правильно насчитал

$ echo "print (2.45 -2)" | python
0.45

Ага, вспомнил, как надо лисп правильно считать заставить:

[1]> (- (/ 245 100) 2)
9/20
[2]>

plm ★★★★★
() автор топика

------------
  float a = 2.45;
  printf("%2.15f\n",a);
------------

2.450000047683716

vsl
()
Ответ на: комментарий от vsl

> printf("%2.15f\n",a-b);

CCЗБ однако ;)

идём и читаем стандарт. float имеет 6 (прописью - ШЕСТЬ) значащих цифр. double - 10 значащих цифр.

sS ★★★★★
()
Ответ на: комментарий от sS

> float имеет 6 (прописью - ШЕСТЬ) значащих цифр. double - 10 значащих цифр.

Хм. А почему об этом не сообщают при компиляции? Это же должно быть легко.

plm ★★★★★
() автор топика
Ответ на: комментарий от plm

>Хм. А почему об этом не сообщают при компиляции? Это же должно быть легко.

Исходя из стандарта получаемый результат не является ошибочным ;)

sS ★★★★★
()
Ответ на: комментарий от vsl

>float имеет 16 значащих двоичных цифр.

Что есть "двоичная цифра" ? 1 бит ? 
Размер float - 4байта (4x8=32бита)
какие такие "16 значащих цифр" имеются ввиду ?

В стандарте чёрным по белому "шесть"
а как известно, float выводится в десятичном а не в двоичном/восмеричном/шестнадцатиречном виде

Маленький пример про "значащие цифры"

#include <iostream>
int main() {
float a=2.45 ;
float b=2.000001;   // 6
float c=2.0000001;  // 7
std::cout << a-b << " vs " << a-c << " sizeof(float)=" << sizeof(float) << "\n";
return 0;
}
ss@toshiba:~$ g++ -O0 test_class.cpp -o test_float
ss@toshiba:~$ test_float
0.449999 vs 0.45 sizeof(float)=4

 речь идёт именно о формате вывода....




 

sS ★★★★★
()
Ответ на: комментарий от vsl

>float имеет 16 значащих двоичных цифр.

А .. я кажется понял. Вы говорите про 8-байтный float (+n.nnnnnnnnnnnnnnnE+eee) а я про тот, что описан в C99

sS ★★★★★
()
Ответ на: комментарий от sS

размер float - 4байта (4x8=32бита)
какие такие "16 значащих цифр" имеются ввиду ?

и что, есть мантиса есть сами значашие цифры.

anonymous
()
Ответ на: комментарий от anonymous

>и что, есть мантиса есть сами значашие цифры.

это 23 бита для float

2^23=8388608 то есть гарантированно имеем именно 6 знаков

как определяется float и double смотри ieee754.h но это конкретная имплементация, а стандарт (в частности C99) говорит именно о _минимально_ количестве значащих цифр.

sS ★★★★★
()
Ответ на: комментарий от dilmah

>ieee754 это не конкретная имплементация. Он четко прописывает формат флоата и дабла.

На данном примере с ieee754.h (в которой описаны IEEE754 и IEEE854) я показываю как конкретная имплементация (*.h) соотносится с C99 стандартом

в любом случае пытаться выводить число с 6 значащими цифрами (23 бита для ieee или 22 для ieee_nan) через 15-значный формат а потом искать смысл в 6+ разрядах - нонсенс.

sS ★★★★★
()
Ответ на: комментарий от sS

> в любом случае пытаться выводить число с 6 значащими цифрами (23 бита для ieee или 22 для ieee_nan) через 15-значный формат а потом искать смысл в 6+ разрядах - нонсенс.

vsl просто показал, откуда неточность берётся. При 2.45 - 2 вылазят те разряды, которые были незначащими и содержали, фактически, мусор.

watashiwa_daredeska ★★★★
()
Ответ на: комментарий от watashiwa_daredeska

>vsl просто показал, откуда неточность берётся. При 2.45 - 2 вылазят те разряды, которые были незначащими и содержали, фактически, мусор.

А я про что говорю ? ;)

Просто мы начинаем ссылатся на разные стандарты где это описывается по разному.

ImHO если приводится код на C то и использоваться должен ANSI/ISO для C (C99)

sS ★★★★★
()
Ответ на: комментарий от sS

> Просто мы начинаем ссылатся на разные стандарты где это описывается по разному.

Да не на разные. Просто, если ты выводишь 2.45 с положенной точностью, то тебе не видно мусора, который в незначащих разрядах. А после -2 у людей недоумение, откуда он берётся. Вот vsl и вывел с чуть бОльшей точностью, чтобы показать, откуда мусор взялся :)

P.S. Мусор этот _не_хранится_ в доп. разрядах. Он возникает из-за ограниченной точности float и того, что 2.45 непредставимо конечной двоичной дробью.

watashiwa_daredeska ★★★★
()
Ответ на: комментарий от watashiwa_daredeska

ага .. в этом и гимор и путаница у начинающих - что любую конечную двоичную дробь можно представить ввиде конечной десятичной, но _не_ любую конечную десятичную ввиде конечной двоичной

lg ★★
()
Ответ на: комментарий от watashiwa_daredeska

>2.45 непредставимо конечной двоичной дробью.

А этого никто и не обещал ;)

Есть такое понятие "заданная точность". Вот с такой точностью (см ANSI/ISO стандарт) и представляют данное число в виде float

sS ★★★★★
()
Ответ на: комментарий от sS

ага - но тут все вкупе и точность и представимость .. вот например

-- tt.c --
int
main()
{
    double d1 = 0.45;
    double d2 = 0.5;
    float f1 = 0.45;
    float f2 = 0.5;

    printf("%d %d\n", d1 == f1, d2 == f2);
    return 0;
}
-- ends here --
$ gcc -o tt tt.c
$ ./tt
0 1

в первом случае 0(не равны) так как 0.45 не представимо ввиде дроби и
как это там называется("эпсилон"?) приближение float и double различны
..

во втором случае 1(равны) так как 0.5 представимо ввиде дроби - 
приближение не играет роли ..

lg ★★
()
Ответ на: комментарий от vsl

Не интересно?? Software Engineer ( UNIX/Linux Kernel) Advance Technology Group is looking for a software engineer to join our advanced development project on fault tolerant computing. You will work within a small team designing and implementing software solution for continuous application availability/fast failover in the Utility Computing environment. Required Skills: MS in Computer Science, Computer Engineering, or equivalent/higher degree. A minimum of 3 to 5 years software engineering experience. Excellent C/C++/UNIX programming skills. Excellent knowledge and deep understanding of UNIX/Linux internals and working experience implementing UNIX/Linux kernel components, preferably not just device drivers, is required. Strong analytical skills are required. Good English is required. Desired Skills: Working experience in distributed programming, understanding of networking fundamentals and hands on experience implementing distributed protocols. zaq44@yandex.ru

swerty
()
Ответ на: комментарий от sS

Это в районе Liverpool st. station (Old Street).

И мне как-то по фиг Лондонские цены - всё равно живу в Кэмбридже... ;)

vsl
()
Ответ на: комментарий от vsl

> http://www.lshift.net/

мне понравились требования к кандидатам:):

you are considered to be opinionated about at least one tech issue you are sometimes observed to be laughing without good reason

dilmah ★★★★★
()

LispWorks 4.4

CL-USER 1 > (- 2.45 0.45) 2.0

CL-USER 2 > (- 2.4545454545454545 0.4545454545454545) 2.0

CL-USER 3 > (- 2.454545454545454523123 2.454545454545454523123) 2.0

CL-USER 4 > 2.454545454545454523123 2.4545454545454546

CL-USER 5 > .454545454545454523123 0.4545454545454545

CL-USER 6 > (- ** *) 2.0

Странно ;-)

anonymous
()

(oops!)(replay :format :user-line-breaks)

LispWorks 4.4
CL-USER 1 > (- 2.45 0.45)
2.0

CL-USER 2 > (- 2.4545454545454545 0.4545454545454545)
2.0

CL-USER 3 > (- 2.454545454545454523123 2.454545454545454523123)
2.0

CL-USER 4 > 2.454545454545454523123
2.4545454545454546

CL-USER 5 > .454545454545454523123
0.4545454545454545

CL-USER 6 > (- ** *)
2.0

Странно ;-)

anonymous
()

LispWorks 4.4

CL-USER 7 > (- 2.45 2) 0.4500000000000002

Понятно. Все в порядке ;-)

anonymous
()

CLISP 2.33.1

[1]> (- 2.45 2)
0.45000005

[2]> (setf *read-default-float-format* 'double-float)
DOUBLE-FLOAT

[3]> (- 2.45 2)
0.4500000000000002

Так то лучше ;-)

anonymous
()
Ответ на: комментарий от anonymous

[3]> (setf *read-default-float-format* 'long-float)

LONG-FLOAT

[4]> (- 2.45 2)

0.45000000000000000004

[5]> (SETF (EXT:LONG-FLOAT-DIGITS) 256)

256

[6]> (- 2.45 2)

0.450000000000000000000000000000000000000000000000000000000000000000000000000007

[7]> (SETF (EXT:LONG-FLOAT-DIGITS) 512)

512

[8]> (- 2.45 2)

0.450000000000000000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000000000000000000000000000000000000000000000006

[9]> (SETF (EXT:LONG-FLOAT-DIGITS) 1024)

1024

[10]> (- 2.45 2)

0.450000000000000000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000000000000000000000000000000000000000004

[11]>

anonymous
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.