revjim.net

May, 2003:

funny PHP math

After my funny math in Python demonstration, Matt decided to do it in Java and then again with even more types. So… I decided to try it in PHP.

Here’s the code:

print("Let's do some math!\n");

$One = 1;
$Ten = 10;
$Pointone = 0.1;

print("loose: 1/10 = " . $One/$Ten . "\n");

$intOne = (int) 1;
$intTen = (int) 10;
$intPointone = (int) 0.1;

print("int: 1/10 = " . ($intOne/$intTen) . "\n");
print("FORCE int: 1/10 = " . (int)($intOne/$intTen) . "\n");

$floOne = (float) 1;
$floTen = (float) 10;
$floPointone = (float) 0.1;

print("float: 1/10 = " . ($floOne/$floTen) . "\n");
print("FORCE float: 1/10 = " . (float)($floOne/$floTen) . "\n");

$sumPointone = 0;
$sumintPointone = (int) 0;
$sumfloPointone = (float) 0;

for($x = 0; $x < 10; $x++) {
        $sumPointone += $Pointone;
        $sumintPointone += $intPointone;
        $sumfloPointone += $floPointone;
}

$multPointone = $Pointone * 10;
$multintPointone = $intPointone * 10;
$multfloPointone = $floPointone * 10;

print("SUM loose: " . $sumPointone . "\n");
print("SUM int: " . $sumintPointone . "\n");
print("SUM FORCE int: " . (int) $sumintPointone . "\n");
print("SUM float: " . $sumfloPointone . "\n");
print("SUM FORCE float: " . (float) $sumfloPointone . "\n");

print("MULT loose: " . $multPointone . "\n");
print("MULT int: " . $multintPointone . "\n");
print("MULT FORCE int: " . (int) $multintPointone . "\n");
print("MULT float: " . $multfloPointone . "\n");
print("MULT FORCE float: " . (float) $multfloPointone . "\n");

And here is the output:

revjim@kilgore:~$ php -q ./math.php
Let's do some math!
loose: 1/10 = 0.1
int: 1/10 = 0.1
FORCE int: 1/10 = 0
float: 1/10 = 0.1
FORCE float: 1/10 = 0.1
SUM loose: 1
SUM int: 0
SUM FORCE int: 0
SUM float: 1
SUM FORCE float: 1
MULT loose: 1
MULT int: 0
MULT FORCE int: 0
MULT float: 1
MULT FORCE float: 1
revjim@kilgore:~$

funny math

Math within a computer will never be perfect. Python, as Matt points out, trys to do the best that it can with what it has. By default, it assumes all numbers are integers and computation using them should only be as accurate as an integer can be. Hence:

>>> 1/10
0

We all know that one divided by ten is 0.1. By Python seems to get it wrong here. Actually, it’s returning floor(1/10) because it assumes that, since you’re using integers, you only want values as accurate as an integer in return. So, we need to force one of the numbers to be a float therefore informing Python that we’re ready to receive a float as a response. We can do that by including a decimal point, or by wrapping the number in the float() function. Like this:

>>> 1/10.0
0.10000000000000001

WHAT? You may be wondering why the value isn’t 0.1. It should be, right? Think about it for a second. A computer stores everything in binary. How would you represent 0.1 in binary? Go ahead… think about it. Well… in binary we’d be actually doing 0001/1010 which would result in the following binary number:

0.0001100110011001100110011001100110011001100110011001100110011001100110011001100110011001100110011001...

That’s right. You can’t accurately store the value of 1/10 in binary. Just like you can’t accurately store the value of 1/3 in decimal. So, python does the best it can by storing a value that is a close approximation to 1/10. And that’s the value it returns.

Okay. So, you understand that. So now, lets compute the value of 1 – 0.9. It should be 0.1:

>>> 1 - 0.9
0.099999999999999978

I’m sure with only a few seconds of thought, you can figure out WHY we get a different value here than we did for 0.1. You see, Python will first compute the value of 0.9 and then figure the value of 1 minus that number. Like this:

>>> x = 0.9
>>> x
0.90000000000000002
>>> 1 - x
0.099999999999999978

You should also notice that 0.1 added to itself 10 times does not equal 1.0:

>>> 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1
0.99999999999999989

And you thought you understood math.

It should be noted that these problems are specific to Python. It is only being used as an example. The same issues exist in most every floating point implementation in almost every programming lanaguage in existance. Do you know of one where this is not the case?

Brave Combo

Jess and I are in. Anyone else?

I don’t particularly enjoy Polka, nor do I particularly enjoy Brave Combo. However, if they’re playing in Keller, it’s got to be worth something.

mod_bw_limited, mod_log_bytes: WHAT?

I think some of my MovableType problems have to do with my webhosting provider. There are two Apache modules installed on my server that I can’t seem to find information on. The first is mod_log_bytes. This seems harmless. The second is mod_bwlimited. Just the name of it makes it seem like, in someway, it could be the culprit of my trouble. Unfortunately, I can only find one piece of information on it, and it’s useless.

I’ve checked my server’s configuration files, and can’t seem to find any configuration options for it either. So I’m not sure where it’s coming from, how it’s configured, or what it actually does.

Do you know?

Python: better than a hammer, if I could just quit hitting my thumb

I’ve been learning Python. What initially was simply a quest to make some small alterations to Pyrite BlogAuthor, has become an all out quest to learn Python. I’ve already seen lots of things that I like. I’ve also seen lots of things that I don’t like, and lots of things that could really get me in trouble.

I’ve also found several… bugs… or limitations. First of all, xmlrpclib doesn’t support an HTTP Proxy. That’s annoying. It should. It only makes sense that it should. However, it does allow you to redefine its transport mechanism, which is almost just as good.

So, after scrounging around here and there, I find the following code that uses urllib which supports an HTTP Proxy:

class UrllibTransport(xmlrpclib.Transport):

        def request(self, host, handler, request_body):
                import urllib
                urlopener = urllib.FancyURLopener()
                urlopener.addheaders = [('User-agent', self.user_agent)]
                # probably should use appropriate 'join' methods instead of 'http://'+host+handler
                f = urlopener.open('http://'+host+handler, request_body)
                return(self.parse_response(f))

Now I don’t fully understand the code above, but that’s never stopped me from going forward in the past, so why should it stop me now? I alter my xmlrpclib.ServerProxy line to use it. I go from this:

self._proxy = xmlrpclib.ServerProxy(self.account.target, verbose=0)

To this:

self.transport = UrllibTransport()
self._proxy = xmlrpclib.ServerProxy(self.account.target, self.transport)

I initially included the verbose=0 portion as well. But that led to odd errors. Removing it led to different errors. Eventually, the only way I could seem to get it to work was to add one additional parameter to UrllibTransport.request: verbose=0. Additionally, I had to also add a self.verbose = verbose, though, I don’t really know why.

Unfortunately, urllib is broken. It sees that I am supplying data (in this case the XML-RPC data) and therefore decides, on its own, that I should make a POST request (which is actually fine in this case). Additionally, regardless of how many times you assign anything to urllib.addheaders, it also adds a Content-Type: application/x-www-form-urlencoded header. Now urllib uses httplib to do its HTTP bidding. And, in what I believe is an attempt at flexibility, httplib will join all the values that have the same header with a comma (“,”). Which means that, if I set my own Content-Type to text/xml (as an XML-RPC call should be, I believe), the actual Content-Type that gets sent is applicaton/x-www-form-urlencoded, text/xml. Yuck!

This wouldn’t be much of an issue, except that I am trying to speak with a Perl XML-RPC implementation. And, in the PERL world, if the Content-Type isn’t either NOTHING at all or text/xml, it screams and yells, and then takes its marbles and goes home.

So, in the end, I’ve learned a lot and yet still haven’t been able to do what I want to do.

Any Python gurus have any pointers?

stupid fuckin’ cable

I installed a new CD-RW drive this evening. It only took me 1.5 hours worth of trouble shooting to determine that, even though it looked perfectly fine and normal, the ribbon cable that came with the drive is bad.

I guess that just goes to show that, regardless of how absurd it sounds, you should never take anything for granted.

Pyrite BlogAuthor is good, MovableType still sucks, and I still can’t bitch

First of all, the reason that Pyrite BlogAuthor didn’t ping the trackbacks associated with the Categories had nothing to do with Pyrite BlogAuthor. It was MovableType’s fault.

After digging through MovableType code for an hour or so (and seriously considering scooping my eyes out with a spoon as an alternative) I found the problem. publishPost, the MovableType specific XMLRPC method, doesn’t ever request that the items to be pinged are pinged. Here’s how you can fix it. Open mt/lib/XMLRPCServer.pm. Find sub publishPost. Look for the line that starts with SOAP::Data_type. Just ABOVE it, add the following:

$mt->ping_and_save( Entry => $entry) or die _fault("Ping and Save failed: " . $mt->errstr);

That’s it. If you use any XMLRPC based blogging client (like w.bloggar and friends) you’ll find that this should fix your problems as well. Unfortunately, I don’t know what other horrible ramifcations this might have. It might send email to your mom and tell her that you masturbate for all I know. However, it seems to work for me.

Pyrite BlogAuthor is very nice. The only thing I don’t like about it is that, when specifying categories, one has to use the category ID as opposed to the category name. One might consider this to be the fault of MovableType and their poorly designed XMLRPC interface. However, at the expense of taking a little bit longer to post an entry, I managed to patch my copy to allow for specifying categories by name.

I don’t know Python, so I’m certain someone more seasoned than myself could do a better job. However, if anyone is interested, I’ll do a diff between my source and the CVS tree so you can implement the changes as well.

Addresses

All of the guests at our wedding, except one (thank you Amanda), didn’t include their address when they signed our guest book. If you attended the wedding, please email me (or Jess) your address.

Thank you.

Pyrite BlogAuthor: not perfect, but almost

While Pyrite BlogAuthor does indeed manage to Post to my MovableType powered weblog, it seems like it either doesn’t send Category pings, or adds the Categories AFTER it requests the entry pings to be sent. Therefore, category based TrackBack pings don’t occur unless you edit the item and then save again. This is not desireable.

Aside from that, a good product. I’ll suggest changing this to the author.

Pyrite BlogAuthor

This post is being written using Pyrite BlogAuthor, a full-featured python based weblog client supporting MovableType, Nucleus, Blogger v1, and others.

I currently use a custom built, GPG enabled mail to blog gateway when I want to post without using the MovableType web-based interface. If this application works properly, it’s flexibility and feature set would be greatly welcomed.