|
Thu, May 08, 2008
![[Link]](http://geekblog.oneandoneis2.org/img/chain_link.gif)
I've been told that, in smug tones of voice, by various people, and seen it written down in a number of places.
So. To the people who think it's useful advice:
My body has been telling me the same thing for half a decade. It can safely assume that I have heard the message. Message received and understood. Really.
What the body really needs is a "Reply" button. Something along the lines of "Yes, I know something is wrong. So howsabout you stop telling me about the problem and get on with FIXING it for a change??"
I think maybe it's the hot weather. Misalignment apparently causes inflammation, which is worsened by heat.
So I'm going to go and get the frozen peas out of the freezer. Again.
And if it doesn't help, I'm going to sulk.
![[Link]](http://geekblog.oneandoneis2.org/img/chain_link.gif)
This weekend, I have to get everything I own packed up into boxes. On Monday, I pack all the boxes onto a van, and on Tuesday, I go to France, where all my worldly goods will be stored whilst I go wandering the world.
Trouble is.. it's always fatal, this sort of thing. You keep coming across stuff you'd packed away. In this case, I've started coming across my scuba gear.
I haven't used it in a while. Rotten weather; seasickness; and a club that insisted on doing its dives in the morning so you had to stagger out of bed at 5am on a Saturday if you wanted to go... all sapped my enthusiasm. And then I got into that year or so of trying to save money to cover me for when I left my job, and that really put a stop to it. One thing scuba diving ISN'T is cheap.
So I put the whole hobby on hold, and packed my gear away in the bottom of a wardrobe. My diving website hasn't been updated in years (still gets several hundred hits a month tho...)
But I came to go through my wardrobe to have a clear-out, and there was all my dive gear... as described here if you want to see it.. Ahh, the nostalgia! If not for the fact that the cylinders are out of test and can't be filled, and solo diving is generally banned at most diving sites, I'd probably have gone for a splash-around in all this hot weather.
Ah well. Maybe in a year or two's time, when I'm back from backpacking and have a job and everything.
Trouble is.. when you start thinking about diving in the future, you start thinking about buying new stuff... and the bit of gear I always wanted to get was a rebreather.
About 90% of diving practice is about managing gas: Having enough to breathe, keeping insulated from the colder water, not letting it cause the bends, etc.
Conventional scuba gear, you breathe in from the cylinders full of compressed air on your back, and breathe it out into the water.
As you probably know, the air is roughly 20% Oxygen and 80% Nitrogen. When you breathe out, it's generally in the region of 80% Nitrogen, 17% Oxygen, and 3% Carbon Dioxide.
So there's a lot of useful gas gets wasted when you breathe out if it just bubbles away.
What's more, because pressure goes up by one atmosphere every 10 meters (30 foot), the gas is twice as dense and therefore you waste twice as much at 10 meters. You waste three times as much at 20m, and four times as much at 30m. Etcetera etcetera.
So if, instead, you were to breathe in and out of a bag, you wouldn't lose the gas. Much more efficient.. except you'd die when you used up the Oxygen. But if you plug in a supply of pure Oxygen to keep it topped up, then you would die of CO2 toxicity instead. Unless you put in a scrubber to remove the CO2.
What you have if you do this is a rebreather: You keep breathing the same gas, removing CO2 and adding O2 to keep it at a breathable level. This can make a huge difference: A 30m dive at 20m could use up some 2000 litres of air with a conventional scuba setup; whereas you would use barely 30 litres of Oxygen and the odd few litres of air on a rebreather.
Advantage one: Smaller cylinders and longer dive times.
Your body does nothing with the Nitrogen. It just takes up space in the air supply. What's more, Nitrogen is narcotic, and makes you start to feel drunk from 30-ish meters down. Additionally, Nitrogen is what gives divers the bends: It dissolves into your body fluids at the higher pressures, then comes out of solution as pressure decreases. Just like a bottle of coke starts to fizz when you open the lid. Come up slowly, that excess gas comes out slowly enough to be gotten rid of safely. Come up too fast, and it's like shaking that bottle of coke before opening it.
You might think that breathing pure Oxygen instead of air would therefore be a great idea: No bends and no narcosis.
And it would, if only Oxygen weren't toxic in high concentrations. You can't breathe pure Oxygen deeper than six meters within recreational diving limits.
But you can increase the amount of Oxygen in the mix you breathe, so instead of air at 20% you have Nitrox at 32% or 36% - it'll cut down on the amount of Nitrogen in your body.
You can also breathe higher-Oxygen mixes as you ascend. 50%, 80% and 100% Oxygen are popular for this. After all, if you have too much Nitrogen in your body, breathing in more of the stuff is going to make it harder for your body to get rid of it than breathing pure Oxygen.
Trouble is.. if you want to breathe 32% at the bottom, and then 50% followed by 100% on the way up, you've got to take at least three cylinders. That's getting heavy!
Unless you're on a rebreather, where you can simply add Oxygen to the air until you have whatever Oxygen percentage you want at any time in the dive.
Advantage 2.
Also, you can replace Nitrogen with some other inert gas to stop it being so narcotic. Helium is used here. It's much less narcotic, but sadly it's a lot more expensive.
A rebreather diver uses much less gas per dive: It's a lot cheaper & easier to use Trimix (Helium/Nitrogen/Oxygen) with his equipment.
Advantage 3.
The downsides?
Well, rebreathers are a lot more expensive. They require a completely different skill set. They can go wrong 'silently'. They require more attention and setting up. And so on.
The first rebreather to make it big in the UK was the Buddy Inspiration: The first rebreather to get CE approval. It has three Oxygen sensors to keep track of your breathing mix, and a computer to keep it at the right amount. If the sensors start to disagree, it uses 'voting logic' to decide which to believe. You're supposed to monitor your Oxygen at all times in case the computer gets it wrong.
I wouldn't buy an Inspiration. It'd be too easy to get used to the computer thinking for me, and stop bothering to monitor it. I know I would get complacent.
I'd buy a KISS. This has three sensors, but no computer. It has a valve that puts in Oxygen at roughly the same speed as your body will use it up, and you handle anything else yourself, manually.
Unlike the Inspiration, then, you can't get complacent and leave it to it. You have to monitor it regularly, because your gas WILL go wrong if you don't.
I like that. I like the way the counterlungs (the bags the gas go into when you breathe out) are on the back instead of the front. I like how simple it is, and how many clever features it's got.
When I finally have the time and opportunity to get back into diving, I'll probably buy a KISS and relearn to dive using a rebreather instead.
If nothing else, that plan guarantees it'll be a few years before I start splashing out on dive gear again :o)
Tue, May 06, 2008
![[Link]](http://geekblog.oneandoneis2.org/img/chain_link.gif)
It's a nice sunny day today. And has been for several days. And I had nothing to do.
So I put my new camping stuff into my rucksack and went for a walk.
Not intending to camp out, you understand. Just to check things like the weight and how easy it was to erect the tent.
I was out for a few hours. The ground was STILL thick mud, so I had to go off-path quite a bit. Into brambles. Wearing shorts.
And it was hot. I had a bottle of water, but it didn't last long. Eventually I stopped for lunch, and pitched my tent.
![[Tent] [Tent]](http://geekblog.oneandoneis2.org/media/blogs/new/tent1.jpg)
![[Tent] [Tent]](http://geekblog.oneandoneis2.org/media/blogs/new/tent2.jpg)
It's a pretty good bit of kit. Astonishingly light, well put-together, and fairly easy to put up. Roomy enough for even my 6'4" self to fit in, and with a space outside to leave my rucksack in.
Then I took it down, packed it back away, and walked another hour or so. All told, I was out nearly three hours. I bought two bottles of drink and an ice-cream while I was out there. They helped.
Overall conclusions:
The new camping stuff was worth the cost. It's light and tough and good at its job.
The Visor Buff is still the comfiest anti-sun headwear I've ever encountered: Keeps the sun out of your eyes and off your neck without any problem.
Espadrills are surprisingly good all-terrain footwear when it's hot.
Taylor's aftershave lotion is the best thing I've ever found to put on my skin. My ankles were scratched to Hell and itching like... something itchy. A liberal smearing of their stuff solved the problem. I guess it makes sense, really: If all you've got is dry skin, any oily gunk will make it feel better. But when it's being applied to freshly-shaved and possibly cut skin.. it's GOT to be good!
And I need a bigger water bottle before I start backpacking properly.
![[Link]](http://geekblog.oneandoneis2.org/img/chain_link.gif)
K&R 4.5: Add things like sin and pow to the calculator
Okay. So you just put in the math.h library and off you go. Right?
Apparently.. wrong.
It SAYS it works, but it gives me the wrong answers for the sin/cos/tan stuff.
1 s
0.84147098
2 s
0.90929743
3 s
0.14112001
Must have coded it wrong.. right?
So let's try something a bit simpler. A bit of code to calculate sin(0-10):
#include <stdio.h>
#include <math.h>
int main()
{
int i;
for (i = 0; i < 11; i++)
printf("sin %d = %f\n", i, sin(i));
return 0;
}
Result?
sin 0 = 0.000000 sin 1 = 0.841471 sin 2 = 0.909297 sin 3 = 0.141120 sin 4 = -0.756802 sin 5 = -0.958924 sin 6 = -0.279415 sin 7 = 0.656987 sin 8 = 0.989358 sin 9 = 0.412118 sin 10 = -0.544021
Same numbers that my calculator code gives me.
But not the same numbers that any other scientific calculator I try gives me.
What's going on??
Mon, May 05, 2008
![[Link]](http://geekblog.oneandoneis2.org/img/chain_link.gif)
In reply to some posts recently, questions have been asked such as "Why learn C instead of going straight to Python?" and "Why implement manually something that's in the standard library anyway?"
Rather than just shunt it into a rather long comment, I'm writing a post on the subject. Here it is.
So.. what difference does the language make? Well, let's take the most recent example I've been working on: A calculator.
If you wanted to do addition in assembly, say 6 + 7, you'd have a laborious bit of work to do. You'd have to write code to load the value of the first number, 6, into one memory register; load the value of the second number, 7, into another memory register; and then tell the computer to add the value of the first memory register to the value of the second register and put the new value into a register so you could do something with it later.
In C, which is rather more abstracted from how the computer 'thinks' you can just tell it to create two variables, and print their combined values: int i = 6; int j = 7; printf("%d plus %d equals %d\n" i, j, (i + j)); will do what you want.
In Python? Well, you run the python executable, and type "6 + 7":
Python 2.5.2 (r252:60911, Feb 21 2008, 13:11:45) [MSC v.1310 32 bit (Intel)] on win32 Type "help", "copyright", "credits" or "license" for more information. >>> 6 + 7 13 >>>
Doesn't get much easier, does it?
Thing is.. when I tried to learn Python a while ago, I was hamstrung because there was too much basic knowledge I didn't have. I could understand what the code said, but I couldn't have written it myself because I didn't know enough.
Sticking with the calculator example: I've known about reverse Polish notation for a long time. Erwin talked like Yoda for a while because of its 'backward' way of entering the two numbers and THEN telling the calculator what to do with them.
I couldn't imagine, years ago, what possible reason there could be for something as daft as this.
In a normal calculator, to find out six plus seven, you type '6' '+' '7' '=' and get the answer. In this thing, you'd have to do '6' 'enter' '7' 'enter' '+' 'enter'
How inefficient! Why would anybody set it up like this??
Because it's how computers work. They take two numbers and perform a function on them. A normal calculator has to remember the numbers and what function you want it to perform. Reverse Polish notation only remembers the numbers, and just performs the function.
It's much quicker and easier to do the sum in Python. But it doesn't give you any idea what the computer's actually DOING when it does that sum. It just does it. All cleverly automated and simple.
The trouble with automation is, it only works when it works. When it doesn't, you need to be able to do it yourself.
The other day, I was struck by something printf does: It turns a number into an ASCII string for you. How, I wondered, did it do that? The number 182, for instance, is stored as the binary number.. just a second... 10110110
Yes, I just worked that out in my head. I like binary. It's a sickness.
So.. how does 10110110 get turned into a '1', an '8', and a '2'? How does it work it out?
It tells you, in K&R. Take your number, use the modulus operator to find the remainder when you divide it by the base you want. That gets you the last digit of the number. Add that to the char '0' and you've got your first character. Then divide the number by your base. Repeat.
This gets you the number, the wrong way round. So reverse it, and you've done your conversion:
182 % 10 = 2
2 + '0' = '2'
182 / 10 = 18
18 % 10 = 8
8 + '0' = '8'
18 / 10 = 1
1 % 10 = 1
1 + '0' = '1'
1 / 10 = 0
Reverse '2' '8' '1' = '1' '8' '2'
Why does it matter? you might ask. printf() does it all for you. There's no value in doing it that way round.
And you're quite right. A %d in printf() will turn 10110110 into "182". Quick and easy.
But.. what if you don't want the decimal value? Or the oct or hex.. what if you've been told to print the answer it base 7? Base 18? Base 3?
If you know how the number is converted into a string, this is no problem. Just a slightly tedious bit of coding. If you rely totally on printf doing it for you.. Well, you're stuffed. Basically.
Before I started learning C, I couldn't understand why reverse Polish notation had ever existed. Upon having to write a calculator, I've discovered that it's the easiest way to write a calculator program.
Yeah, maybe I could get by without the knowledge. The world is FULL of people that can write all kinds of software without knowing the nuts & bolts of it.
But the world is also full of people that can't use a language that doesn't do garbage collection for them. It's full of people who can only write code where 9/10s of the work has been done for them by somebody else.
The parallels between writing code and using software are fairly blatant. Take Linux: How successful it's becoming recently, with Ubuntu and PCLinuxOS and Suse etc. The numbers of users are going up all the time.
Because a while ago, people were saying "We've got this really good powerful system, but it takes time and effort for people to be able to use it." And they 'fixed' this problem by automating things, stopping people being obliged to do them.
There was a time when you had to compile a custom kernel to get Linux working properly on your system. There was a time when you were unable to use it unless you knew how to use the CLI. There was a time when virtually every Linux user had an opinion on the "vi or emacs?" question.
Trawl through the Ubuntu forums. See just how many users today have to be hand-held through every step of using the CLI when they have a problem. There are people out there using Linux every day who have no idea how to even get to the CLI, let alone how to use it. They don't NEED to know, and they're HAPPY not to.
Good for them.
I'm not.
For me, a Linux computer without a CLI is worse than Windows. I can cope without Firefox, without Pidgin, without VLC.. but not without bash.
Because whilst things being done automatically by a clever bit of software may work 99 times out of 100... that 1 in 100 time can be a killer.
I once lost my grub config file. I booted up to nothing but a grub prompt. It was a 10-second inconvenience, because I know how to use grub, and I told it where to find the kernel and what partition to make the root, and in less than a minute I was back into my fully-functional Linux OS. The average 'new' Ubuntu user? Wouldn't stand a chance.
XMMS wouldn't start once. No error message, it showed up in a 'ps', I just didn't get anything on my screen. Ever. No message telling me why. It just didn't work. Even re-installing it didn't fix it. I launched it from the CLI via the strace command and discovered it was trying to access a /tmp file. Deleting that file fixed the problem. Solving that problem without the CLI? As far as I know, it couldn't be done.
My computer locked up every time I booted once. It got as far as starting the X prompt, and then froze. So I told grub to pass it the "Don't start X" command, scanned the X error messages with less, discovered that it was crashing because it couldn't find /dev/mouse, edited udev's conf file to create a symlink /dev/mouse to /dev/psaux, and then started X manually. Problem solved.
Solved, not by helpful forums or a nearby Linux guru. Solved by me, because I know how to use Linux without all the GUIs and helpful wizards. Because where some people have only ever used Ubuntu, I started with Slackware, moved onto LinuxFromScratch, spent a long time on Gentoo, and only THEN came to try out Ubuntu.
Yes, most of the time, it's pointless knowing what's going on under the hood. The majority of people spend the majority of time not knowing or caring.
I'm not the majority of people.
I don't like helpful software. I don't like having config files I don't know how to edit by hand. I don't want to just shrug and let the standard library do things without having a clue how it does them. I don't like the attitude of "If a language doesn't fix my mistakes, it's a crap language" which is what most "C is rubbish because it doesn't do garbage collection" arguments boil down to.
C isn't a bad language, and it doesn't have memory management problems. The only problem it has is the age-old PEBKAC one. YOU have to use it properly. Languages like Python are a lot more forgiving, but if all you know is Python, then you're going to have the same problems that a user who only knows Ubuntu has: Sometimes, it WON'T do it for you, and you won't know how to do it yourself.
As the old saying goes: Linux is user-friendly. It's just very selective about who its friends are.
I hope that answers the questions about why I'm learning C, and why I'm learning it in the way I am :o)
![[Link]](http://geekblog.oneandoneis2.org/img/chain_link.gif)
It's a Bank Holiday. May day.
The world has gone wrong: It's warm and sunny. Has been all weekend.
When I went out jogging, I actually wore my short-sleeved top and shorts. And was too hot. And finished my bottle of water before I got back.
Even after a fairly long shower, I was still sweating enough that my shaving foam kept being washed off my face. Once I'd finally managed to shave, I almost wanted another shower to rinse off the sweat that had accumulated since getting out of the shower the first time.
I'm not hugely fond of living in a hot climate. And here I am, planning on heading south for an extended period. Let's hope it'll be easier to cope with when it's not such a rarity :o)
Sun, May 04, 2008
![[Link]](http://geekblog.oneandoneis2.org/img/chain_link.gif)
Moving swiftly on: Add more commands to do stuff with the stack. Simplest is, of course, best: Single character commands, here we come!
I went for ? as a 'print topmost' and it's simple enough: Instead of just 'popping' the value, you assign it to the 'op2' variable that we already have for remembering popped numbers, and then you can 'push' it back to the stack after printing it. As an added bonus, you can use it mid-expression to print out values as you go along:
10? 4 -? 3 -? 2 -? 1 -
10
6
3
1
0
Duplication is easy: Pop it once, push it twice. It's an easy way to do exponential maths:
1?d+?d+?d+?d+?d+
1
2
4
8
16
32
Swapping them, again not hard, but you DO need another variable: Unlike swapping two values in an array, which only needs one, the stack loses its value when you 'pop' it.
Or so it seemed.
But I didn't like all the inefficiency. What's the point of adding variables to remember things in main() that you've just told pop() to forget, when you can just modify 'pop' so it's more selective? All this poncing about with adding variables in main() to remember because pop() is brainlessly forgetting... No. This is a perfect example of adding overall complexity to keep a small amount of simplicity.
I decided to do a bit more work to get a more efficient and versatile chunk of code. I went back to the drawing board, undid the changes I'd made to the code, and went to meddle with the pop() function instead.
Simple enough: First, some #define's to make the code more clear:
#define LOSE 0 #define KEEP 1 #define SWAP 2 #define CLEAR 3
Then a find&replace to change all existing instances of 'pop()' to 'pop(LOSE)' and quickly change 'double pop(void)' to 'double pop(int)'.
pop() can now be passed arguments to make it more intelligent about what it does. If it's passed a LOSE when called, it 'pops' as usual, but if it gets a KEEP, it 'pops' without removing a value from the stack. Etc. etc.
Time to re-write my new functionality taking advantage of the better pop(). And the code's much nicer now: Instead of '?' doing a pop-to-variable + print-variable + push-variable, it just prints with a lossless-pop. Duplication just pushes a lossless pop. Swapping is done by the function that has access to the array, and clearing is done in pop rather than by adding yet another function.
Considering the C answer book uses the same 'pop to variables' approach I started with, I think I've actually done pretty well here: I've wound up with less calculations and no need for an extra 'clear' function to be added. Mine does everything through a better pop()
Smug mode :o)
The obligatory test: I entered this string and then pressed enter until it emptied the stack. Looks fine to me!
99?99?99?c1 2 4 3 s 5 6 d
99
99
99
Stack cleared
6
6
5
4
3
2
1
error: stack empty
0
Innit marvellous?
![[Link]](http://geekblog.oneandoneis2.org/img/chain_link.gif)
Finally, I have the time and the inclination both at once to write some C.
4.3 asks you to add the modulus operator % and provision for negative numbers.
The modulus operator takes you back to early schooldays when you hadn't learned about decimals, when 42 divided by 10 was 4 remainder 2. - The modulus gives the remainder, 42 % 10 = 2
I was going to do the modulus in a complicated way: For i % j, I was going to do:
a = i / j
i - (a * j)
So, with the 42 % 10, you'd get:
a = 42/10 = 4
42 - (4 * 10) = 42 - 40 = 2
Which would have worked. But then it occurred to me, What the Hell am I thinking, just use the modulus operator in the code, moron! so I just copied the division code and replaced / with %
Heh.
It didn't work.
invalid operands to binary %
That stumped me.
Then I went back to those schooldays I mentioned earlier. We used 4 remainder 2 because we didn't have decimals. What was the code passing to %? Doubles. Double-precision floating point numbers. Decimal numbers. No remainders.
I've never had to use a cast before. But replacing push(pop() % op2); with push((int) pop() % (int) op2); fixed the problem for me.
Trivial, really.. Such simple little mistakes make for such buggy software :o)
Next, adding negative number support. Tricky. You have to make it differentiate between a - sign meaning a minus number, and a - sign meaning "subtract". Same character, different meaning. Hmmm...
Can't be done in main(), we'll have to differentiate in the getop() function instead.
To start with, obviously, one must change the line that says 'if this isn't a digit or a period, it's not a number, so return it as-is' to instead say 'if this isn't a digit or a period or a minus sign, it's not a number, so return it as-is'
Then you have to decide what to do if it's a minus sign.
First, I was going to go the simple route: If it's a minus sign followed by a space, it means 'subtract', otherwise it's a minus number.
Then I realized that you can have a minus followed by another minus, or a plus, or a divide, or...
Scrub that. We need to do it properly: If the minus sign is followed by a number or a period.
If it is, it's a minus number. If it isn't, it's a subtract. So return a '-'
Oh, and put whatever followed into the buffer, it might be important.
Oh, unless it's an EOF.
Sigh. I didn't catch that last one - the C answer book pointed it out to me. Oh well, live and learn!
All done, I compiled and got an error message. I'd left out a }
Out of practice? Moi?
Fixed it, and it compiled without issue. As test of the new functionality, I decided to try the sum (103 % 10)(-10 - -14) and see if I got 12 as the answer.
(103 % 10)*(-10 - -14)
[(103 % 10) = 3 ] * [(-10 - -14) = (-10 + 14) = 4]
3 * 4 = 12
So, here goes:
$ gcc -Wall polish43.c -o polish
$ ./polish
103 10 % -10 -14 -*
12
Woohoo! :o)
Not the most trouble-free bit of coding I ever did. I'm badly out of practice in thinking through programming logic, and doing things like brackets properly. But I got it all done in the end, which is what counts at the moment...
I also had to look up the sed command I'd aliased as the 'blogify' command on my old laptop to be able to C&P the code to here, so here it is while I remember:
sed -e 's/</\</g' -e 's/>/\>/g' filename
:: Next Page >>
| Mon | Tue | Wed | Thu | Fri | Sat | Sun |
|---|---|---|---|---|---|---|
| << < | > >> | |||||
| 1 | 2 | 3 | 4 | |||
| 5 | 6 | 7 | 8 | 9 | 10 | 11 |
| 12 | 13 | 14 | 15 | 16 | 17 | 18 |
| 19 | 20 | 21 | 22 | 23 | 24 | 25 |
| 26 | 27 | 28 | 29 | 30 | 31 | |