Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Reproducing java calculations in UNIX

37 views
Skip to first unread message

archidemon

unread,
Jun 24, 2009, 9:43:40 PM6/24/09
to
I need to reproduce some decimal fractions. Here are a few examples:

256/626
0.40894568690095845

512/918
0.5577342047930284

256/2504
0.10223642172523961

256/3672
0.06971677559912855

I have good reasons to believe they are the results of calculations
made in Java. Consequently they would be computed as IEEE doubles,
and then the binary double values are being printed to enough decimal
places to allow them to be reconstructed exactly.

I also know that:

awk 'BEGIN{printf "%1.17f\n", 256/626}'
0,40894568690095845

awk 'BEGIN{printf "%1.16f\n", 512/918}'
0,5577342047930284

awk 'BEGIN{printf "%1.17f\n", 512/918}'
0,55773420479302838

awk 'BEGIN{printf "%1.17f\n", 256/2504}'
0,10223642172523961

awk 'BEGIN{printf "%1.17f\n", 256/3672}'
0,06971677559912855

Thus printf "%1.17f\n" cannot explain everything probably in part
because trailing zeroes would be removed.

What would be the way to emulate those Java calculations with UNIX
tools like AWK or bc for instance?

Thank you!

Greg Russell

unread,
Jun 24, 2009, 11:23:30 PM6/24/09
to
In news:66b61d2e-a05f-45d1...@g20g2000vba.googlegroups.com,
archidemon <mike...@gmail.com> typed:

> I need to reproduce some decimal fractions. Here are a few examples:
> 256/626
> 0.40894568690095845

...


> What would be the way to emulate those Java calculations with UNIX
> tools like AWK or bc for instance?

$ echo "scale=50;256/626" | bc
.40894568690095846645367412140575079872204472843450


Marcel Bruinsma

unread,
Jun 25, 2009, 3:08:45 AM6/25/09
to
archidemon wrote:

> I need to reproduce some decimal fractions. Here are a few examples:
>
> 256/626
> 0.40894568690095845
>
> 512/918
> 0.5577342047930284
>
> 256/2504
> 0.10223642172523961
>
> 256/3672
> 0.06971677559912855
>
> I have good reasons to believe they are the results of calculations
> made in Java. Consequently they would be computed as IEEE doubles,
> and then the binary double values are being printed to enough decimal
> places to allow them to be reconstructed exactly.
>

[...]


>
> What would be the way to emulate those Java calculations with UNIX
> tools like AWK or bc for instance?

I doubt bc can help out, it emulates bcd computations. You're
looking for something that does binary64 IEEE 754, like awk
or perl.

Here's an (incomplete) example in C; maybe you can
translate to awk or perl:

$ cc -o rnd rnd.c
$ ./rnd 256 626
0.40894568690095845
$ ./rnd 512 918
0.5577342047930284
$ ./rnd 256 2504
0.10223642172523961
$ ./rnd 256 3672
0.06971677559912855
$ cat rnd.c
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
int
main(int ac, char **av)
{
union { double d; uint64_t i; } u;
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;

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;
u.d = x; u.i += 1; b = u.d;

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;
}
printf("%s\n",s[1]);

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! #

draftman

unread,
Jun 25, 2009, 10:36:44 AM6/25/09
to
snip

Thank you! My C training dates from the early '90s, I will see what i
can get.

draftman

unread,
Jun 25, 2009, 8:19:51 PM6/25/09
to
snip

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?

Marcel Bruinsma

unread,
Jun 26, 2009, 1:52:34 AM6/26/09
to
draftman wrote:

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);

draftman

unread,
Jun 28, 2009, 4:53:25 PM6/28/09
to
Thank you!

I took what you very gently provided VERY SERIOUSLY and that why I am
going to follow it.

I just have some problem on translating it in AWK involving the
transformation of the binary representation of a 64 bit double to a 64
bit integer and back. I am working on those.

I especially thank you for the routine that provides the precision I
need. I will work on that one after.

Marcel Bruinsma

unread,
Jun 28, 2009, 10:28:19 PM6/28/09
to
draftman wrote:

> I just have some problem on translating it in AWK involving the
> transformation of the binary representation of a 64 bit double to a 64
> bit integer and back. I am working on those.

Since awk is probably closer to perl, than it is to C, it might offer
functionality similar to the perl pack/unpack functions.

Example in perl:

$quotient = 512/918;
$bs = pack 'd',$quotient;
$uns64 = unpack 'Q',$bs;
$uns64 += 1;
$bs = pack 'Q',$uns64;
$successor = unpack 'd',$bs;

KingKong

unread,
Jun 29, 2009, 8:13:09 AM6/29/09
to
snip

> Example in perl:
>
> $quotient = 512/918;
> $bs = pack 'd',$quotient;
> $uns64 = unpack 'Q',$bs;
> $uns64 += 1;
> $bs = pack 'Q',$uns64;
> $successor = unpack 'd',$bs;

Thank you!

I saw that perl has that very usefull Q pack. I don't see that
quadratic option for AWK. Maybe If I were to create a string that
would be compose of:

the sign bit of the quotient,
the same 11 bit of the exponent of the quotient
51 zeroes
1

Would that be an equivalent of that 1 that is added or subtracted
without having to use a converstion to integer?

Marcel Bruinsma

unread,
Jun 30, 2009, 1:10:30 AM6/30/09
to
KingKong wrote:

> I saw that perl has that very usefull Q pack. I don't see that
> quadratic option for AWK. Maybe If I were to create a string
> that would be compose of:
>
> the sign bit of the quotient,
> the same 11 bit of the exponent of the quotient
> 51 zeroes
> 1
>
> Would that be an equivalent of that 1 that is added or subtracted
> without having to use a converstion to integer?

No, that won't work: the integer part of the mantissa would
still be one (per definition). But this _might_ work:

the sign bit of the quotient

(the 11 bits of the exponent of the quotient) minus 52
52 zero bits

For example: (with 2 bit fraction, in stead of 52 bits)
0.01 * 2**0 == 0.10 * 2**-1 == 1.00 * 2**-2
The respective biased exponents (11 bits wide) are
1023, 1022, and 1021. The rightmost representation
is normalised (integer part is one).

KingKong

unread,
Jul 1, 2009, 1:24:05 AM7/1/09
to
On Jun 30, 1:10 am, Marcel Bruinsma <we-love-all-s...@gmail.com>
wrote:

> KingKong wrote:
> > I saw that perl has that very usefull Q pack. I don't see that
> > quadratic option for AWK. Maybe If I were to create a string
> > that would be compose of:
>
> > the sign bit of the quotient,
> > the same 11 bit of the exponent of the quotient
> > 51 zeroes
> > 1
>
> > Would that be an equivalent of that 1 that is added or subtracted
> > without having to use a converstion to integer?
>
> No, that won't work: the integer part of the mantissa would
> still be one (per definition). But this _might_ work:
>
> the sign bit of the quotient
> (the 11 bits of the exponent of the quotient) minus 52
> 52 zero bits
>
> For example: (with 2 bit fraction, in stead of 52 bits)
>   0.01 * 2**0 == 0.10 * 2**-1 == 1.00 * 2**-2
> The respective biased exponents (11 bits wide) are
> 1023, 1022, and 1021. The rightmost representation
> is normalised (integer part is one).

I want to be sure I get it. I can replace the 1 that is added and
substracted with:

the sign bit of the quotient

(the 11 bits of the exponent of the quotient) minus 52 = 10101111111
52 zero bits

52 zero bits
0101011111110000000000000000000000000000000000000000000000000000

123456789012345678901234567890123456789012345678901234567890123456789
1 2
3 4 5 6

Am I right?

Marcel Bruinsma

unread,
Jul 1, 2009, 9:18:38 AM7/1/09
to
KingKong wrote:

>> For example: (with 2 bit fraction, in stead of 52 bits)
>> 0.01 * 2**0 == 0.10 * 2**-1 == 1.00 * 2**-2
>> The respective biased exponents (11 bits wide) are
>> 1023, 1022, and 1021. The rightmost representation
>> is normalised (integer part is one).
>
> I want to be sure I get it. I can replace the 1 that is added and
> substracted with:
>
> the sign bit of the quotient
> (the 11 bits of the exponent of the quotient) minus 52 = 10101111111
> 52 zero bits

I'm not sure where that “10101111111” (1407 in decimal) came from.

But what I meant with “minus 52” is: extract the biased exponent
(11 bits wide) of the quotient, then subtract 52 from that value,
and use the result of that subtraction as the biased exponent of
the delta value. For example:

quotient = 256 / 918
64 bit double representation is 0x3fd1d8f5672e4abd :
sign = 0
exp = 011_1111_1101 (decimal: 1021)
frac = 0001_11011000_11110101_01100111_00101110_01001010_10111101

The new biased exponent is (01111111101 - 110100), or (1021 - 52) in
decimal notation, which is 969, or 01111001001 in binary notation. The
new 64 bit double (delta) is:
sign = 0
exp = 011_1100_1001 (decimal: 969)
frac = 0000_00000000_00000000_00000000_00000000_00000000_00000000
in hexadecimal notation: 0x3c90000000000000
Which is 2**-54, or approximately 5.5511E-17

Then,
successor = quotient + delta
predecessor = quotient - delta

KingKong

unread,
Jul 2, 2009, 10:39:45 PM7/2/09
to
I have my back on the wall here. Either I find a way to put the binary
representation of doubles in a string using bash tools or I have to
learn to incorporate pearl in my shell scripting.
What will be the way?

Marcel Bruinsma

unread,
Jul 3, 2009, 5:50:03 AM7/3/09
to
KingKong wrote:

Perhaps, a shell function?
With a little help from perl? :)

#!/bin/bash
rqs () {
perl -e '
$sign = 0;
if (($numerator = $ARGV[0]) < 0) {
$numerator = -$numerator;
$sign = 1;
}
if (($denominator = $ARGV[1]) < 0) {
$denominator = -$denominator;
$sign = 1-$sign;
}
$quotient = $numerator / $denominator;


$bs = pack "d",$quotient;

$qi = unpack "Q",$bs;
$bs = pack "Q",++$qi;


$successor = unpack "d",$bs;

$bs = pack "d",$quotient;

$qi = unpack "Q",$bs;
$bs = pack "Q",--$qi;
$predecessor = unpack "d",$bs;
for ($precision = 1;;++$precision) {
$qs = sprintf "%.${precision}f",$quotient;
$ss = sprintf "%.${precision}f",$successor;
last if $qs ne $ss;
}
for (;;++$precision) {
$qs = sprintf "%.${precision}f",$quotient;
$ps = sprintf "%.${precision}f",$predecessor;
last if $qs ne $ps;
}
$quotient = -$quotient if $sign;
printf "%.${precision}f",$quotient;
' $1 $2
}

foo="$(rqs 512 918)"
echo "$foo"

Ben Bacarisse

unread,
Jul 3, 2009, 11:33:51 AM7/3/09
to
KingKong <mike...@gmail.com> writes:

I have not been following this thread so no doubt I've missed either a
constraint or maybe even the overall purpose, but:

VAR=$(printf %A 0.125)

fits at least one interpretation of your words.

--
Ben.

KingKong

unread,
Jul 3, 2009, 11:13:13 PM7/3/09
to
Am I doomed?

Look I copied on the terminal of my completely up to date mac 10.5.7:

foo="$(rqs 512 918)"


****
And I got:
****
Invalid type 'Q' in unpack at -e line 13.
$ echo "$foo"

****
just to check, I did:
****

$ perl -v

This is perl, v5.8.8 built for darwin-thread-multi-2level
(with 4 registered patches, see perl -V for more detail)

Copyright 1987-2006, Larry Wall

Perl may be copied only under the terms of either the Artistic License
or the
GNU General Public License, which may be found in the Perl 5 source
kit.

Complete documentation for Perl, including FAQ lists, should be found
on
this system using "man perl" or "perldoc perl". If you have access to
the
Internet, point your browser at http://www.perl.org/, the Perl Home
Page.

****
Am I hopeless?

KingKong

unread,
Jul 3, 2009, 11:20:21 PM7/3/09
to
On Jul 3, 11:33 am, Ben Bacarisse <ben.use...@bsb.me.uk> wrote:

Maybe I am working with an obsolete environnement:

$ echo $(printf %A 0.125)
-bash: printf: 0.125: invalid number
0X0P+0

Here is what I have:
perl -V
Summary of my perl5 (revision 5 version 8 subversion 8) configuration:
Platform:
osname=darwin, osvers=9.0, archname=darwin-thread-multi-2level
uname='darwin b02.apple.com 9.0 darwin kernel version 9.3.0: tue
aug 12 17:18:07 pdt 2008; root:xnu-1228.5.90~13release_i386 i386 '
config_args='-ds -e -Dprefix=/usr -Dccflags=-g -pipe -Dldflags= -
Dman3ext=3pm -Duseithreads -Duseshrplib'
hint=recommended, useposix=true, d_sigaction=define
usethreads=define use5005threads=undef useithreads=define
usemultiplicity=define
useperlio=define d_sfio=undef uselargefiles=define usesocks=undef
use64bitint=define use64bitall=define uselongdouble=undef
usemymalloc=n, bincompat5005=undef
Compiler:
cc='cc', ccflags ='-arch ppc -arch i386 -g -pipe -fno-common -
DPERL_DARWIN -no-cpp-precomp -fno-strict-aliasing -Wdeclaration-after-
statement -I/usr/local/include',
optimize='-O3',
cppflags='-no-cpp-precomp -arch ppc -g -pipe -fno-common -
DPERL_DARWIN -no-cpp-precomp -fno-strict-aliasing -Wdeclaration-after-
statement -I/usr/local/include'
ccversion='', gccversion='4.0.1 (Apple Inc. build 5465)',
gccosandvers=''
intsize=4, longsize=4, ptrsize=4, doublesize=8, byteorder=1234
d_longlong=define, longlongsize=8, d_longdbl=define,
longdblsize=16
ivtype='long', ivsize=4, nvtype='double', nvsize=8, Off_t='off_t',
lseeksize=8
alignbytes=8, prototype=define
Linker and Libraries:
ld='cc -mmacosx-version-min=10.5.7', ldflags ='-arch ppc -arch
i386 -L/usr/local/lib'
libpth=/usr/local/lib /usr/lib
libs=-ldbm -ldl -lm -lutil -lc
perllibs=-ldl -lm -lutil -lc
libc=/usr/lib/libc.dylib, so=dylib, useshrplib=true,
libperl=libperl.dylib
gnulibc_version=''
Dynamic Linking:
dlsrc=dl_dlopen.xs, dlext=bundle, d_dlsymun=undef, ccdlflags=' '
cccdlflags=' ', lddlflags='-arch ppc -arch i386 -bundle -undefined
dynamic_lookup -L/usr/local/lib'


Characteristics of this binary (from libperl):
Compile-time options: MULTIPLICITY PERL_IMPLICIT_CONTEXT
PERL_MALLOC_WRAP USE_ITHREADS USE_LARGE_FILES
USE_PERLIO USE_REENTRANT_API
Locally applied patches:
fix for regcomp CVE-2007-5116 security vulnerability
fix for double-free CVE-2008-1927 security vulnerability
/Library/Perl/Updates/<version> comes before system perl directories
installprivlib and installarchlib points to the Updates directory
Built under darwin
Compiled at Mar 11 2009 16:09:08
%ENV:
PERL5LIB="/sw/lib/perl5:/sw/lib/perl5/darwin"
@INC:
/sw/lib/perl5
/sw/lib/perl5/darwin
/Library/Perl/Updates/5.8.8
/System/Library/Perl/5.8.8/darwin-thread-multi-2level
/System/Library/Perl/5.8.8
/Library/Perl/5.8.8/darwin-thread-multi-2level
/Library/Perl/5.8.8
/Library/Perl
/Network/Library/Perl/5.8.8/darwin-thread-multi-2level
/Network/Library/Perl/5.8.8
/Network/Library/Perl
/System/Library/Perl/Extras/5.8.8/darwin-thread-multi-2level
/System/Library/Perl/Extras/5.8.8
/Library/Perl/5.8.6
/Library/Perl/5.8.1
.

Ben Bacarisse

unread,
Jul 4, 2009, 6:38:26 AM7/4/09
to
KingKong <mike...@gmail.com> writes:

> On Jul 3, 11:33 am, Ben Bacarisse <ben.use...@bsb.me.uk> wrote:
>> KingKong <mikeom...@gmail.com> writes:
>> > I have my back on the wall here. Either I find a way to put the binary
>> > representation of doubles in a string using bash tools or I have to
>> > learn to incorporate pearl in my shell scripting.
>> > What will be the way?
>>
>> I have not been following this thread so no doubt I've missed either a
>> constraint or maybe even the overall purpose, but:
>>
>>   VAR=$(printf %A 0.125)
>>
>> fits at least one interpretation of your words.
>>
>> --
>> Ben.

It's better to snip sig blocks.

> Maybe I am working with an obsolete environnement:
>
> $ echo $(printf %A 0.125)
> -bash: printf: 0.125: invalid number
> 0X0P+0

Odd. It works on the only Mac OSX version I can access right now:

$ uname -v
Darwin Kernel Version 9.7.0: Tue Mar 31 22:52:17 PDT 2009; root:xnu-1228.12.14~1/RELEASE_I386

> Here is what I have:
> perl -V

Perl is not involved in this.

--
Ben.

Ben Bacarisse

unread,
Jul 4, 2009, 6:42:06 AM7/4/09
to
KingKong <mike...@gmail.com> writes:

> Am I doomed?
>
> Look I copied on the terminal of my completely up to date mac 10.5.7:
>
> #!/bin/bash
> rqs () {
> perl -e '

<snip>


> $qi = unpack "Q",$bs;
> $bs = pack "Q",++$qi;

<snip>


> ' $1 $2
> }
>
> foo="$(rqs 512 918)"
>
> ****
> And I got:
> ****
> Invalid type 'Q' in unpack at -e line 13.
> $ echo "$foo"

Yes, some versions of Perl are compiler without support for the Q
pack/unpack format.

<snip>
--
Ben.

Marcel Bruinsma

unread,
Jul 4, 2009, 2:44:22 PM7/4/09
to
KingKong wrote:

> ****
> And I got:
> ****
> Invalid type 'Q' in unpack at -e line 13.

Your perl is compiled for 32 bit OS.

This might work for little endian arch; if your CPU
is big endian, switch iH and iL in the two lines
marked with “####”.

#!/bin/bash
rqs () {
perl -e '
$sign = 0;
if (($numerator = $ARGV[0]) < 0) {
$numerator = -$numerator;
$sign = 1;
}
if (($denominator = $ARGV[1]) < 0) {
$denominator = -$denominator;
$sign = 1-$sign;
}
$quotient = $numerator / $denominator;
$bs = pack "d",$quotient;

#$qi = unpack "Q",$bs;
($iH,$iL) = unpack "LL",$bs;
#$qi += 1;
++$iH; ++$iL unless $iH &= 0xffffffff; ####
#$bs = pack "Q",$qi;
$bs = pack "LL",$iH,$iL;


$successor = unpack "d",$bs;
$bs = pack "d",$quotient;

#$qi = unpack "Q",$bs;
($iH,$iL) = unpack "LL",$bs;
#$qi -= 1;
($iH = 0xffffffff,--$iL) unless $iH--; ####
#$bs = pack "Q",$qi;
$bs = pack "LL",$iH,$iL;


$predecessor = unpack "d",$bs;
for ($precision = 1;;++$precision) {
$qs = sprintf "%.${precision}f",$quotient;
$ss = sprintf "%.${precision}f",$successor;
last if $qs ne $ss;
}
for (;;++$precision) {
$qs = sprintf "%.${precision}f",$quotient;
$ps = sprintf "%.${precision}f",$predecessor;
last if $qs ne $ps;
}
$quotient = -$quotient if $sign;
printf "%.${precision}f",$quotient;
' $1 $2
}

foo="$(rqs 512 918)"

Marcel Bruinsma

unread,
Jul 4, 2009, 2:45:02 PM7/4/09
to
KingKong wrote:

> On Jul 3, 11:33 am, Ben Bacarisse <ben.use...@bsb.me.uk> wrote:
>>

>> VAR=$(printf %A 0.125)


>
> $ echo $(printf %A 0.125)
> -bash: printf: 0.125: invalid number
> 0X0P+0

Looks like a “locale” problem.

$ printf '%A\n' 0.125


bash: printf: 0.125: invalid number
0X0P+0

$ printf '%A\n' 0,125
0X8P-6
$ echo $LANG
nl_NL.UTF-8

LANG, LC_ALL and LC_NUMERIC are the locale
environment variables that define the decimal point.

KingKong

unread,
Jul 4, 2009, 10:28:28 PM7/4/09
to
First, thank you a lot it worked, I will be able to move on with my
life!

snip

> > Invalid type 'Q' in unpack at -e line 13.
>
> Your perl is compiled for 32 bit OS.

I am very disapointed with leopard. I am expecting Snow Leopard will
be all 64 bits. Will the following code work as well then?


> This might work for little endian arch; if your CPU
> is big endian, switch iH and iL in the two lines
> marked with “####”.
>

I am going to keep that in mind if a the upgrade to snow leopard
(coming in a few months) change that aspect.

snip

Thank you again!

KingKong

unread,
Jul 4, 2009, 10:32:44 PM7/4/09
to
snip

> $ printf '%A\n' 0.125
> bash: printf: 0.125: invalid number
> 0X0P+0
> $ printf '%A\n' 0,125
> 0X8P-6
> $ echo $LANG
> nl_NL.UTF-8
>
> LANG, LC_ALL and LC_NUMERIC are the locale
> environment variables that define the decimal point.

snip

on my system:
$ echo $LANG
fr_CA.UTF-8
$ echo $LC_ALL

$ echo $LC_NUMERIC

$

Is the problem my french canadian environment or the lack of LC_ALL
and LC_NUMERIC?

Marcel Bruinsma

unread,
Jul 5, 2009, 1:07:19 AM7/5/09
to
KingKong wrote:

> on my system:
> $ echo $LANG
> fr_CA.UTF-8
> $ echo $LC_ALL
>
> $ echo $LC_NUMERIC
>

> Is the problem my french canadian environment or the lack
> of LC_ALL and LC_NUMERIC?

If none of those three is set, the default locale (POSIX,
with decimal delimiter ‘.’) will be used. If all three are
set LC_ALL has highest priority. If LC_ALL is unset,
then LC_NUMERIC is used. Last in line is LANG,
which takes effect only if the other two are unset.

If at least one of LANG, LC_NUMERIC or LC_ALL
is set to fr_CA (or fr_BE or fr_FR) the decimal
delimiter will be a comma, on input as well as on
output.

$ echo "|$LANG|$LC_ALL|$LC_NUMERIC|"
|fr_CA.UTF-8|||
$ printf '%A\n' 4.321
bash: printf: 4.321: invalid number
0X0P+0
$ printf '%A\n' 4,321
0X8.A45A1CAC083126FP-1
$ LC_NUMERIC=POSIX # LC_NUMERIC overrides LANG
$ printf '%A\n' 4.321
0X8.A45A1CAC083126FP-1

Marcel Bruinsma

unread,
Jul 5, 2009, 1:08:42 AM7/5/09
to
KingKong wrote:

>> Your perl is compiled for 32 bit OS.
>
> I am very disapointed with leopard. I am expecting Snow Leopard
> will be all 64 bits. Will the following code work as well then?

Yes. The ‘L’ is always 32 bits wide, independent from the length
of the native C compiler's ‘long’.

KingKong

unread,
Jul 5, 2009, 1:49:47 PM7/5/09
to
snip the whole thing.

I am amazed how good you are!

Where is the documentation for this rounding process?

Is it called "exact precision"?

Thank you again!

0 new messages