Re: Reproducing java calculations in UNIX



draftman wrote:

What I can grasp is that a and b are read as double, the
quotient goes in x, also a double.
The sign is checked, it is an integral part IEEE double.
The quotient is printed with printf("%s\n",s[1])

Do I understand the trick is to divide 2 double and to output the
quotient as another double?
The must be something I don't get. Am I not?

The 64 bit double format is:
- bit 63 : sign (0 = positive; 1 = negative)
- bits 52..62 : biased exponent (11 bits)
- bits 0..51 : fraction (52 bits)

The bias value for the exponent is 1023.

For normalised numbers (i.e. the biased exponent
is greater than zero) only the fractional part of the
mantissa is stored, the integer part is always one.
Think of these numbers as: (ignoring sign)
1.fraction * 2**(biased_exponent - 1023)

The decimal number 1.0 is:
0x3ff__0_0000_0000_0000 (1.0...0 * 2**0)
{fraction is 52 zero bits, shortened to "0...0"}
The decimal number 2.0 is:
0x400__0_0000_0000_0000 (1.0...0 * 2**1)
{fraction is 52 zero bits, shortened to "0...0"}

The smallest number that is greater than 2.0 is:
0x400__0_0000_0000_0001 (1.0...1 * 2**1)
{fraction is 51 zero bits followed by a one bit}
{biased exponent is 1024; sign is zero}
The largest number that is less than 2.0 is:
0x3ff__f_ffff_ffff_ffff (1.1...1 * 2**0)
{fraction is 52 one bits}
{biased exponent is 1023; sign is zero}

Step by step in C:

int
main(int ac, char **av)
{
union { double d; uint64_t i; } u;

* Consider this union as an 8 byte memory area.
* It can be used to store/retrieve a 64 bit double
* value (referenced as u.d) or to store/retrieve a
* 64 bit integer value (referenced as u.i).
* If x is of type double, and y of type uint64, then
* "u.d = x; y = u.i;" is just a simple way of getting the
* 64 bits of the double value into an integer variable,
* to perform common integer operations.

char s[3][64];
double a,b,x;
uint64_t y;
int i;

if (ac != 3) abort();
a = strtod(av[1],NULL);
b = strtod(av[2],NULL);
u.d = x = a/b;

* The first command line argument (the numerator)
* is converted from string to floating point (string
* to double) and temporarily stored in variable a.
* The denominator (second argument) goes to var b.
* The division (a/b) is performed (hopefully by IEEE
* 754 compliant FPU e.g., x87, mc68882), and the
* result stored in variable x (also type double) and in
* the union (u.d).

* Forget about the next three lines. These tests on the
* fractional part of the mantissa make no sense at all.
* y = UINT64_C(0xfffffffffffff);
* if ((y & u.i) == y) abort();
* if ((y & u.i) == 0) abort();

u.d = x; u.i -= 1; a = u.d;
* elaborate version:
* u.d = x; Store 64 bit double.
* y = u.i; Retrieve value as 64 bit integer.
* y = y - 1; Perform integer subtraction.
* u.i = y; Store 64 bit integer result.
* a = u.d; Retrieve the same bits as a double.
* Et voila, the double value that is closest to, but less
* than x (the predecessor of x), is now in variable a.

u.d = x; u.i += 1; b = u.d;
* Similar story, the double value closest to, but greater
* than x (the successor of x), goes to variable b.

* The following loop is a brute force approach to find the
* smallest precision, where the decimal representation
* (ASCII string) of x differs from the strings for a and b.
*
* Starting with a precision of one, all three numbers are
* 'printed' to a string (s[...]), then the strings are compared.
* Return value zero (from strcmp()) means strings are equal,
* other values mean not equal. If one of the comparisons
* returns equal (zero), the precision is increased and the
* loop continues.
for (i=1;;++i) {
sprintf(s[0],"%.*f",i,a);
sprintf(s[1],"%.*f",i,x);
sprintf(s[2],"%.*f",i,b);
if (strcmp(s[1],s[0])
&& strcmp(s[1],s[2]))
break;
}
* When s[1] (x) differs from s[0] (a) and s[2] (b) the
* search is over. The minimum precision, necessary
* for a unique representation of x (the quotient), is
* in variable i, and the string for x in s[1].

printf("%s\n",s[1]);
* or alternatively: printf("%.*f\n",i,x);

return 0;
}

--
printf -v email $(echo \ 155 141 162 143 145 154 142 162 165 151 \
156 163 155 141 100 171 141 150 157 157 056 143 157 155|tr \ \\\\)
# Live every life as if it were your last! #
.



Relevant Pages

  • REPRESENT revisited
    ... Forth-94 has few floating point display functions [none in the ... If u is greater than zero the character string shall consist ... If u is zero the string shall consist of one digit representing ...
    (comp.lang.forth)
  • Re: REPRESENT revisited
    ... >has given rise to implementations that differ in critical ... The required compatibility is 1), but 2) makes it much easier to get ... > If u is zero the string shall consist of one digit representing ... But I think it is a very bad idea if a word that should fill a string ...
    (comp.lang.forth)
  • Re: Allow Zero Length String Property - 2000 vs 2003
    ... Are you the same person who posted the 'Allow Zero Length String in MS ... "Ash" wrote in message ...
    (microsoft.public.access.tablesdbdesign)
  • spacing issue with drawing a string into a JScrollPane
    ... The string is a representation of a whole number & fraction number group. ... int wholeNumberStringWidth; ... wholeNumberFractionGap, y - 10); ...
    (comp.lang.java.gui)
  • RE: Macro Question
    ... The string you want Microsoft Excel to search for. ... SearchOrder Optional Variant. ... The settings for LookAt, SearchOrder, MatchCase, and MatchByte are saved ... > include a search for occurrences of zero. ...
    (microsoft.public.excel.programming)