Hi again: Another silly program... #include <iostream> #include <cln/lfloat.h> #include <cln/lfloat_io.h> using namespace cln; int main(int argc, char **argv) { default_float_format=float_format(100); cl_LF a,b,c; b="1e-60"; a="1.0"; c=a+b; std::cerr << "c=" << c << std::endl; c=c-a; std::cerr << "c=" << c << std::endl; } And the outputs are 1.0L and 0.0L ¿What happen with the default_float_format?. If I write a="1.00000000000000000000000 ..." (100 zeros here) I obtain the same result, then b is lost somewhere. More, when b about < 1e-20 then it is lost. Maybe an error in the conversion? Bye. -- *************************************************************************** * Dr. Isidro Cachadiña Gutiérrez * * Departamento de Física * * Facultad de Ciencias * * Universidad de Extremadura * * 06071 Badajoz ( SPAIN ) * * email: icacha@unex.es * * Teléfono: +34 924 289 300 Ext. 6826 Fax: +34 924 289 651 * *************************************************************************** * Usuario Linux: 8569 * * Para clave pública GnuPG: http://onsager.unex.es/firma.pub.asc * ***************************************************************************
Hi otra vez, On Fri, 10 Dec 2004, Isidro [iso-8859-15] Cachadiña Gutiérrez wrote:
#include <iostream> #include <cln/lfloat.h> #include <cln/lfloat_io.h>
using namespace cln; int main(int argc, char **argv) {
default_float_format=float_format(100); cl_LF a,b,c; b="1e-60"; a="1.0"; c=a+b; std::cerr << "c=" << c << std::endl; c=c-a; std::cerr << "c=" << c << std::endl; }
And the outputs are 1.0L and 0.0L ¿What happen with the default_float_format?. If I write a="1.00000000000000000000000 ..." (100 zeros here) I obtain the same result, then b is lost somewhere.
More, when b about < 1e-20 then it is lost. Maybe an error in the conversion?
El Viernes, 10 de Diciembre de 2004 22:48, Richard B. Kreckel escribió:
Hi otra vez,
On Fri, 10 Dec 2004, Isidro [iso-8859-15] Cachadiña Gutiérrez wrote:
#include <iostream> #include <cln/lfloat.h> #include <cln/lfloat_io.h>
using namespace cln; int main(int argc, char **argv) {
default_float_format=float_format(100); cl_LF a,b,c; b="1e-60"; a="1.0"; c=a+b; std::cerr << "c=" << c << std::endl; c=c-a; std::cerr << "c=" << c << std::endl; }
And the outputs are 1.0L and 0.0L ¿What happen with the default_float_format?. If I write a="1.00000000000000000000000 ..." (100 zeros here) I obtain the same result, then b is lost somewhere.
More, when b about < 1e-20 then it is lost. Maybe an error in the conversion?
From the documentation:
4.1.3 Constructing floating-point numbers -----------------------------------------
`cl_F' objects with low precision are most easily constructed from C `float' and `double'. See *Note Conversions::.
........
Hello Richard and Bruno: I'm sorry to tell you that you don't understand that I wanted to say, because it is related to the use of the global variable default_float_format, and not with the floating point representation but I will explain it. Lets begin. First, with your documentation the function float_format_t float_format( uintL n) "Returns the smallest float format wich guarantees at least n _decimal_ digits in the mantissa (after the decimal point)" (see _undelined_ the word decimal digits) That is, being q the number of binary digits of the mantisa can be established the relation 2^-q = 10^-n then q = n log 10/log 2 and with n = 100 then q = 332 bits approximately. Then, following the documentation the line default_float_format=float_format(100); should guarantize at least 332 bits in the mantissa, aproximately ¿right?. When I define b="1e-60"; a="1.0"; Can I expect that these numbers will be represented with 332 mantissa bits, or not?. If not, there is a bug cause the global variable has not effect. Or it is a feature?, I'll discuss it later... If yes, there is a bug cause in the result the b is truncated about 1e-20 which is approximately 60 mantissa bits, and it is so close to the number of mantissa bit of the double type.
`cl_F' objects with low precision are most easily constructed from C `float' and `double'. See *Note Conversions::.
I think, because I have not read all the source code that there is a problem in the decimal to binary conversion that don't read the default_float_format variable before convert it to numbers), and then it has not effect.
To construct a `cl_F' with high precision, you can use the conversion from `const char *', but you have to specify the desired precision within the string. (See *Note Internal and printed representation::.) Example: cl_F e = "0.271828182845904523536028747135266249775724709369996e+1_40"; will set `e' to the given value, with a precision of 40 decimal digits.
Then is you don't consider the above behaviour as bugs, then I have a wish. The "programatic way" to define a number with the desired precission is good when you know how many decimal digits you need, but, for example I have a case in which I don't know how many digits I will need and I have to do with trial and error procedure. Then, the default_float_format must behave in this way: a = 5.0; then 5.0 have to be converted to a 330 bits (if I choose 100 decimal digits) and in all algebraical operations like b=a*2.72/c*7.28. all numbers have to be converted to the default_float_format that I have specified.
The programmatic way to construct a `cl_F' with high precision is through the `cl_float' conversion function, see *Note Conversion to floating-point numbers::. For example, to compute `e' to 40 decimal places, first construct 1.0 to 40 decimal places and then apply the exponential function: float_format_t precision = float_format(40); cl_F e = exp(cl_float(1,precision));
Then programatic way that you have proposed is not good for long proyects cause you have to define a variable number of digits and then apply to all the conversions and things like b=a*2.72/c*7.28 become as the ugly b = a*cl_float(2.72,precission)/c*cl_float(7.28,precision); But, .....let us read my first e-mail...
#include <iostream> #include <cln/real.h> #include <cln/real_io.h>
using namespace cln;
int main(int argc, char **argv) { default_float_format=float_format(100); cl_R a,b; b=cl_float(1e-1,default_float_format); a=cl_float(1,default_float_format); a=a+b; std::cerr << "a=" << a << std::endl; }
The output is:
a=1.1000000000000000055511151231257827021181583404541015625L0 > ^ ¿Why are here these noisy digits?. They are so close ..
Upss. It doesn't work. ¿a bug?. The difference it is that I used default_float_format instead precission and the conversion of 1e-1 was done with approximately the double precission cause the noisy digits 55111... are about the 19 decimal digit not about the desired 100.
It appears like you are still totally confused about the relation between decimal and binary representation. Please do have a close look at the paper by David Goldberg that Bruno Haible has recommended in an earlier thread!
If with all things that I wrote above you still think that I am confused with the relation between decimal and binary representation then I have a big problem, cause I think that two first mails were so clear about the problem.
What do you think a close approximation of 1/10 decimal in binary float is, provided you have 300 binary digits? Hint: the mantissa doesn't end in all zeros. Rather in 11001100110011001100....
Since CLN neither does BCD nor is psychic, all decimal numbers must be approximated for a binary representation. Now, since your input was not an (exact) rational number, but rather some float with limited precision, CLN did approximate as much as was reasonable. But not more.
Hasta la proxima -richy.
A ver si esta vez nos enteramos del problema. -- *************************************************************************** * Dr. Isidro Cachadiña Gutiérrez * * Departamento de Física * * Facultad de Ciencias * * Universidad de Extremadura * * 06071 Badajoz ( SPAIN ) * * email: icacha@unex.es * * Teléfono: +34 924 289 300 Ext. 6826 Fax: +34 924 289 651 * *************************************************************************** * Usuario Linux: 8569 * * Para clave pública GnuPG: http://onsager.unex.es/firma.pub.asc * ***************************************************************************
El Lunes, 13 de Diciembre de 2004, Isidro Cachadiña Gutiérrez escribió:
El Viernes, 10 de Diciembre de 2004 22:48, Richard B. Kreckel escribió:
Hi otra vez,
On Fri, 10 Dec 2004, Isidro [iso-8859-15] Cachadiña Gutiérrez wrote:
#include <iostream> #include <cln/lfloat.h> #include <cln/lfloat_io.h>
using namespace cln; int main(int argc, char **argv) {
default_float_format=float_format(100); cl_LF a,b,c; b="1e-60"; a="1.0"; c=a+b; std::cerr << "c=" << c << std::endl; c=c-a; std::cerr << "c=" << c << std::endl; }
And the outputs are 1.0L and 0.0L ¿What happen with the default_float_format?. If I write a="1.00000000000000000000000 ..." (100 zeros here) I obtain the same result, then b is lost somewhere.
More, when b about < 1e-20 then it is lost. Maybe an error in the conversion?
From the documentation:
4.1.3 Constructing floating-point numbers -----------------------------------------
`cl_F' objects with low precision are most easily constructed from C `float' and `double'. See *Note Conversions::.
........
Hello Richard and Bruno:
I'm sorry to tell you that you don't understand that I wanted to say, because it is related to the use of the global variable default_float_format, and not with the floating point representation but I will explain it.
Lets begin.
First, with your documentation the function
float_format_t float_format( uintL n)
"Returns the smallest float format wich guarantees at least n _decimal_ digits in the mantissa (after the decimal point)" (see _undelined_ the word decimal digits)
That is, being q the number of binary digits of the mantisa can be established the relation
2^-q = 10^-n
then q = n log 10/log 2
and with n = 100 then q = 332 bits approximately. Then, following the documentation the line
default_float_format=float_format(100);
should guarantize at least 332 bits in the mantissa, aproximately ¿right?.
Basically yes, that's right. On a machine with 32 Bit words (intDsize==32) that would be rounded up to some 352 bits in the mantissa because CLN doesn't bother to use fractions of words.
When I define
b="1e-60"; a="1.0";
Can I expect that these numbers will be represented with 332 mantissa bits, or not?.
No. Use cl_float(x,y) for that. And remember that cl_float returns a cl_F, not a cl_LF.
If not, there is a bug cause the global variable has not effect. Or it is a feature?, I'll discuss it later...
Feature. goto later;
If yes, there is a bug cause in the result the b is truncated about 1e-20 which is approximately 60 mantissa bits, and it is so close to the number of mantissa bit of the double type.
Just one hopefully clarifying remark: This is because you specifically asked CLN to construct a cl_LF, which is at least as large as double. You end up with two machine words, which is 64 Bit and that is quite close to 20 decimal digits.
`cl_F' objects with low precision are most easily constructed from C `float' and `double'. See *Note Conversions::.
I think, because I have not read all the source code that there is a problem in the decimal to binary conversion that don't read the default_float_format variable before convert it to numbers), and then it has not effect.
later: Nobody expects you to read all the sources. But the documentation clearly states (4.11.1 Conversion to floating-point numbers): `float_format_t default_float_format' Global variable: the default float format used when converting rational numbers to floats. To convert a real number to a float, each of the types `cl_R', `cl_F', `cl_I', `cl_RA', `int', `unsigned int', `float', `double' defines the following operations: `cl_F cl_float (const TYPE&x, float_format_t f)' Returns `x' as a float of format `f'. `cl_F cl_float (const TYPE&x, const cl_F& y)' Returns `x' in the float format of `y'. `cl_F cl_float (const TYPE&x)' Returns `x' as a float of format `default_float_format' if it is an exact number, or `x' itself if it is already a float. I think that you are doing things with floating point numbers that are documented to work with rationals only.
To construct a `cl_F' with high precision, you can use the conversion from `const char *', but you have to specify the desired precision within the string. (See *Note Internal and printed representation::.) Example: cl_F e = "0.271828182845904523536028747135266249775724709369996e+1_40"; will set `e' to the given value, with a precision of 40 decimal digits.
Then is you don't consider the above behaviour as bugs, then I have a wish. The "programatic way" to define a number with the desired precission is good when you know how many decimal digits you need, but, for example I have a case in which I don't know how many digits I will need and I have to do with trial and error procedure. Then, the default_float_format must behave in this way:
a = 5.0;
then 5.0 have to be converted to a 330 bits (if I choose 100 decimal digits) and in all algebraical operations like
b=a*2.72/c*7.28.
all numbers have to be converted to the default_float_format that I have specified.
No. In a large project this would not be a good idea because any deterioration of precision due to lower precision in some of the input variables would go undetected. I do think it was a brilliant idea to require people to write down the complete cl_float(double,float_format_t) spell. I also think that something in your approach is broken if you wish to control the imact of double precision floating point variables on 100 decimal digit precision floating point variables.
The programmatic way to construct a `cl_F' with high precision is through the `cl_float' conversion function, see *Note Conversion to floating-point numbers::. For example, to compute `e' to 40 decimal places, first construct 1.0 to 40 decimal places and then apply the exponential function: float_format_t precision = float_format(40); cl_F e = exp(cl_float(1,precision));
Then programatic way that you have proposed is not good for long proyects cause you have to define a variable number of digits and then apply to all the conversions and things like b=a*2.72/c*7.28 become as the ugly
b = a*cl_float(2.72,precission)/c*cl_float(7.28,precision);
Unless that statement is inside a loop anyway (in which case the constant factor ought to be hoisted out) I would write that such things rather as b = cl_float( 2.72*7.28, precision ) * a / c; because of efficiency anyways. Or did you mean b = cl_float( 2.72/7.28, precision ) * a / c; by chance?
But, .....let us read my first e-mail...
#include <iostream> #include <cln/real.h> #include <cln/real_io.h>
using namespace cln;
int main(int argc, char **argv) { default_float_format=float_format(100); cl_R a,b; b=cl_float(1e-1,default_float_format); a=cl_float(1,default_float_format); a=a+b; std::cerr << "a=" << a << std::endl; }
The output is:
a=1.1000000000000000055511151231257827021181583404541015625L0 > ^ ¿Why are here these noisy digits?. They are so close ..
Upss. It doesn't work.
*What* does not work?
¿a bug?. The difference it is that I used default_float_format instead precission
You are not implying that it makes a difference if you use your own variable of type float_format_t instead of the global default_float_format, are you? If you think you have found a bug, please send a test program as small as possible, tell us what it does for you, and what you expected it to do. Otherwise, we won't be able to help you.
and the conversion of 1e-1 was done with approximately the double precission cause the noisy digits 55111... are about the 19 decimal digit not about the desired 100.
Me parece que todavía no existe una traducción de <http://www.chiark.greenend.org.uk/~sgtatham/bugs.html>. ¡Vaya!
It appears like you are still totally confused about the relation between decimal and binary representation. Please do have a close look at the paper by David Goldberg that Bruno Haible has recommended in an earlier thread!
If with all things that I wrote above you still think that I am confused with the relation between decimal and binary representation then I have a big problem, cause I think that two first mails were so clear about the problem.
Maybe you aren't confused. But your bug reports sure are confusing. :-) [...]
A ver si esta vez nos enteramos del problema.
Parece que no. Hasta la vista -richy. -- Richard B. Kreckel <http://www.ginac.de/~kreckel/>
Hello again. It seems that I am "improving" the list traffic, :-).
Can I expect that these numbers will be represented with 332 mantissa bits, or not?.
No. Use cl_float(x,y) for that. And remember that cl_float returns a cl_F, not a cl_LF.
Yes. Now all my floats are cl_F.
If not, there is a bug cause the global variable has not effect. Or it is a feature?, I'll discuss it later...
Feature. goto later;
If yes, there is a bug cause in the result the b is truncated about 1e-20 which is approximately 60 mantissa bits, and it is so close to the number of mantissa bit of the double type.
Just one hopefully clarifying remark: This is because you specifically asked CLN to construct a cl_LF, which is at least as large as double. You end up with two machine words, which is 64 Bit and that is quite close to 20 decimal digits.
Then. The main difference is that, by default, cl_F and cl_LF have different precission unless you specify it, right?. If it is true it was not clear for me in the documentation.
`cl_F' objects with low precision are most easily constructed from C `float' and `double'. See *Note Conversions::.
I think, because I have not read all the source code that there is a problem in the decimal to binary conversion that don't read the default_float_format variable before convert it to numbers), and then it has not effect.
later: Nobody expects you to read all the sources. But the documentation clearly states (4.11.1 Conversion to floating-point numbers):
`float_format_t default_float_format' Global variable: the default float format used when converting rational numbers to floats.
To convert a real number to a float, each of the types `cl_R', `cl_F', `cl_I', `cl_RA', `int', `unsigned int', `float', `double' defines the following operations:
`cl_F cl_float (const TYPE&x, float_format_t f)' Returns `x' as a float of format `f'.
`cl_F cl_float (const TYPE&x, const cl_F& y)' Returns `x' in the float format of `y'.
`cl_F cl_float (const TYPE&x)' Returns `x' as a float of format `default_float_format' if it is an exact number, or `x' itself if it is already a float.
I think that you are doing things with floating point numbers that are documented to work with rationals only.
Yes, maybe.
No. In a large project this would not be a good idea because any deterioration of precision due to lower precision in some of the input variables would go undetected.
Ok. This is the phylosophy of your library, but it is tedious for me (I don't know if for other people also) , to rewrite all sources and conversions of numbers as cl_float(x,y).
I do think it was a brilliant idea to require people to write down the complete cl_float(double,float_format_t) spell.
I also think that something in your approach is broken if you wish to control the imact of double precision floating point variables on 100 decimal digit precision floating point variables.
No.
b = a*cl_float(2.72,precission)/c*cl_float(7.28,precision);
Unless that statement is inside a loop anyway (in which case the constant factor ought to be hoisted out) I would write that such things rather as b = cl_float( 2.72*7.28, precision ) * a / c;
Yes, of course, It was only an example. I was two days working in my program in order to write all floats as cl_float(float,precision) on arithmetic expressions and checking for the correct precission. But I am writing better: b=cl_float(2.72/7.28,a)*a/c;
You are not implying that it makes a difference if you use your own variable of type float_format_t instead of the global default_float_format, are you? If you think you have found a bug, please send a test program as small as possible, tell us what it does for you, and what you expected it to do. Otherwise, we won't be able to help you.
and the conversion of 1e-1 was done with approximately the double precission cause the noisy digits 55111... are about the 19 decimal digit not about the desired 100.
Maybe you aren't confused. But your bug reports sure are confusing. :-)
Well. Is this a bug and is it well reported? .. ------------------------------------------------------------------------------------------ #include <iostream> #include <cln/float.h> #include <cln/float_io.h> using namespace cln; int main(int argc, char **argv) { // Wrong result? float_format_t prec; prec=float_format(100); cl_F a,b,c; b=cl_float(1.0e-10,prec); a=cl_float(1.0,prec); c=a+b; std::cerr << "Incorrect: " << std::endl; std::cerr << "c=" << c << std::endl; c=c-a; std::cerr << "c=" << c << std::endl; // Right result std::cerr << "Correct:" << std::endl; a="1.0_100"; b="1.0e-10_100"; c=a+b; std::cerr << "c=" << c << std::endl; c=c-a; std::cerr << "c=" << c << std::endl; } -------------------------------------------------------------------------------------- The output in my computer. =================================================== Incorrect: c=1.00000000010000000000000000364321973154977415791655470655996396089904010295867919921875L0 c=1.0000000000000000364321973154977415791655470655996396089904010295867919921875L-10 Correct: c=1.0000000001L0 c=9.999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999997972106604L-11 =================================================== A ver si esta vez... -- *************************************************************************** * Dr. Isidro Cachadiña Gutiérrez * * Departamento de Física * * Facultad de Ciencias * * Universidad de Extremadura * * 06071 Badajoz ( SPAIN ) * * email: icacha@unex.es * * Teléfono: +34 924 289 300 Ext. 6826 Fax: +34 924 289 651 * *************************************************************************** * Usuario Linux: 8569 * * Para clave pública GnuPG: http://onsager.unex.es/firma.pub.asc * ***************************************************************************
El Martes, 14 de Diciembre de 2004 08:47, Isidro Cachadiña Gutiérrez escribió:
Well. Is this a bug and is it well reported? .. --------------------------------------------------------------------------- --------------- #include <iostream> #include <cln/float.h> #include <cln/float_io.h>
using namespace cln; int main(int argc, char **argv) {
// Wrong result?
float_format_t prec; prec=float_format(100);
cl_F a,b,c; b=cl_float(1.0e-10,prec); a=cl_float(1.0,prec); c=a+b;
std::cerr << "Incorrect: " << std::endl;
std::cerr << "c=" << c << std::endl; c=c-a; std::cerr << "c=" << c << std::endl;
// Right result
std::cerr << "Correct:" << std::endl;
a="1.0_100"; b="1.0e-10_100"; c=a+b;
std::cerr << "c=" << c << std::endl; c=c-a; std::cerr << "c=" << c << std::endl;
} --------------------------------------------------------------------------- ----------- The output in my computer. =================================================== Incorrect: c=1.00000000010000000000000000364321973154977415791655470655996396089904010 295867919921875L0 c=1.00000000000000003643219731549774157916554706559963960899040102958679199 21875L-10 Correct: c=1.0000000001L0 c=9.99999999999999999999999999999999999999999999999999999999999999999999999 9999999999999999999999999999999997972106604L-11 ===================================================
A ver si esta vez...
Well. I answer myself. This is a feature since the conversion is done at running time, then 1e-10 is stored as 1.000......3643e-10 and the cl_float anly can add zeroes. But this functionality is good then perhaps a mix between a="number_<precision> " can be done : for example float_format_t prec; prec=float_format(100); a=cl_float("1.0e-10",prec); a function cl_F cl_float(char *,float_format_t) I haven't the documentation here now and I don't remenber if this function is implemented yet but I'll be happy if this functions is somewhere. Thanks. -- *************************************************************************** * Dr. Isidro Cachadiña Gutiérrez * * Departamento de Física * * Facultad de Ciencias * * Universidad de Extremadura * * 06071 Badajoz ( SPAIN ) * * email: icacha@unex.es * * Teléfono: +34 924 289 300 Ext. 6826 Fax: +34 924 289 651 * *************************************************************************** * Usuario Linux: 8569 * * Para clave pública GnuPG: http://onsager.unex.es/firma.pub.asc * ***************************************************************************
El Martes, 14 de Diciembre de 2004 00:21, Richard B. Kreckel escribió:
b = a*cl_float(2.72,precission)/c*cl_float(7.28,precision);
Unless that statement is inside a loop anyway (in which case the constant factor ought to be hoisted out) I would write that such things rather as b = cl_float( 2.72*7.28, precision ) * a / c;
mmm .... I'm not sure because of perhaps 2.72*7.28 is converted to a float and then ... let see: #include <iostream> #include <cln/float.h> #include <cln/float_io.h> using namespace cln; int main(int argc, char **argv) { cl_F a,b; a="1.0_100"; a=cl_float(9.0/7.0,a)*a; std::cout << a << std::endl; b="1.0_100"; b=cl_float(9,b)/cl_float(7,b)*b; std::cout << b << std::endl; } --- The output --- 1.2857142857142858094476878250134177505970001220703125L0 1.2857142857142857142857142857142857142857142857142857142857142857142857142857142857142857142857142857142857142857143L0 Better the second, no? Nos vemos. -- *************************************************************************** * Dr. Isidro Cachadiña Gutiérrez * * Departamento de Física * * Facultad de Ciencias * * Universidad de Extremadura * * 06071 Badajoz ( SPAIN ) * * email: icacha@unex.es * * Teléfono: +34 924 289 300 Ext. 6826 Fax: +34 924 289 651 * *************************************************************************** * Usuario Linux: 8569 * * Para clave pública GnuPG: http://onsager.unex.es/firma.pub.asc * ***************************************************************************
participants (2)
-
Isidro Cachadiña Gutiérrez
-
Richard B. Kreckel