Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl-Sensitive Sunglasses
 
PerlMonks  

Re^5: Variables are automatically rounded off in perl (humans)

by pryrt (Abbot)
on Jul 22, 2016 at 14:14 UTC ( [id://1168363]=note: print w/replies, xml ) Need Help??


in reply to Re^4: Variables are automatically rounded off in perl (humans)
in thread Variables are automatically rounded off in perl

BrowserUK did a good job of explaining the real issue, which you now get, but I wanted to further clarify a tangential point:

... for literal floating point values you would in general have to write them in a number base of a power of two if you want to express ... them exactly.

It's one of the mathematical niceties of binary that any binary floating point can be exactly represented in decimal. It comes about because 2 (binary) is a factor of 10 (decimal: 2*5)

x = c * (2**p) # the value you want to express c # the coefficient p = -n # the smallest power of two that goes into x; # negative, since it's a binary fraction x = c*(2**p) = c*(2**-n) = ... [ 1 ] [ 1 ] [ 5**n ] [ 5**n ] = ... = c*[------] = c*[------]*[------] = c*[-------] = ... [ 2**n ] [ 2**n ] [ 5**n ] [ 10**n ] = ... = c * (5**n) * (10**-n) = c * (5**n) ** (10**p) k = c * (5**n) # k integer, so exactly representable in decimal x = k * (10**-n) # since n is finite and k is an integer, # x is exactly representable in decimal

As might be obvious from the final statement, an n-digit binary fixed point can be expressed exactly in an n-digit decimal fixed point.

It turns out, there's something else interesting you can tell about the number of digits for an exact power of two: specifically, which digit d (after the decimal point) that the decimal expansion will start on

x c*(2**-n) binary decimal d log10(x) 1/2 1*(2**-1) 0b0.1 0.5 1 -0.301029996 1/4 1*(2**-2) 0b0.01 0.25 1 -0.602059991 3/4 3*(2**-2) 0b0.11 0.75 1 -0.124938737 1/8 1*(2**-3) 0b0.001 0.125 1 -0.903089987 7/8 7*(2**-3) 0b0.111 0.875 1 -0.057991947 1/16 1*(2**-4) 0b0.0001 0.0625 2 -1.204119983 15/16 15*(2**-4) 0b0.1111 0.9375 1 -0.028028724 1/32 1*(2**-5) 0b0.00001 0.03125 2 -1.505149978 1/64 1*(2**-6) 0b0.000001 0.015625 2 -1.806179974 1/128 1*(2**-7) 0b0.0000001 0.0078125 3 -2.107209970 3/128 3*(2**-7) 0b0.0000011 0.0234375 2 -1.630088715 5/128 5*(2**-7) 0b0.0000101 0.0390625 2 -1.408239965 9/128 9*(2**-7) 0b0.0001001 0.0703125 2 -1.152967460 13/128 13*(2**-7) 0b0.0001101 0.1015625 1 -0.993266617

You might see that d = -floor(log10(x)) = ceil(-log10(x)). In general, for a given x = c*(2**-n) < 1, the decimal expression will start on the dth digit after the decimal point, and end on the nth digit after the decimal point; thus, the length of the decimal expansion (ignoring leading and trailing zeroes) is L = n - d + 1.

For example, the smallest representable 52bit fraction x = 2**-52 = 2.2204...e-16: it will start on the 16th digit (log10(x)=-15.654 -> d=16) and run to the 52nd digit. Double precision floating-point numbers (the common native floating-point in perl5) use a 52bit fractional component, with the encoding usually meaning one plus the fractional part times some power of two (x = (1+f)*(2**p)). So, that (1+f) can be exactly expressed in decimal as

1.0000 0000 0000 000f ffff ffff ffff ffff ffff ffff ffff ffff ffff ^1 16^ 52^ + ^ points to the nth digit after decimal point

And thus, you need the 16 digits after the decimal point to indicate the last bit of accuracy in the underlying binary fraction, as BrowserUK said. (But you would need all 52 decimal digits after the decimal point to exactly represent the full value.)

Sorry, I like stuff like this: all this to say: you can exactly represent any n-digit binary fraction within n decimal digits after the decimal point.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://1168363]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others meditating upon the Monastery: (4)
As of 2024-04-19 21:39 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found