Arduino Timer

I was recently playing around with my Arduino Uno, and, out of curiosity, I tried to make it play a musical note, by attaching the output to a speaker from a telephone. However, when I compared the result to the actual note on my piano, I found that that the note from the Arduino was a whole tone too high (12% too fast). I tried this for 440hz and for 220hz, and got the same result. Is there a limit to the accuracy of the Arduino timer of around 100?s that's reflected here, or is there something else going on?
For reference, here is the code I used.

int speaker = 12;
void setup() {
  pinMode(speaker, OUTPUT);
}
void loop() {
  digitalWrite(speaker, HIGH);
  delay(2.272);
  digitalWrite(speaker, LOW);
  delay(2.272);
}
int speaker = 12;
void setup() {
  pinMode(speaker, OUTPUT);
}
void loop() {
  digitalWrite(speaker, HIGH);
  delay(1.136);
  digitalWrite(speaker, LOW);
  delay(1.136);
}

I did not know that delay(ms) might work with a non integer number of ms.
I'd read somewhere that miilis() is not that accurate.

On a nano v.3 328 type arduino, delayMicroseconds(1200); would work more repeatably than delay(1.2);
The time returned by micros() was off by +- 3 parts in 10000 and drifted with time of day (possibly temperature?) by +- 1 part in 10000 per half-day during a couple of days. It was different by 4 parts in 10000 on a second nominally identical nano.

I hope that gives you some hard figures to know what you can expect.

I don't know about that speaker phone, the impedance could be too low, or it has a heavy coil which could have dangerous inductivity for the Arduino.

There is a tone library:

Have a look at the Audio in the Playground section : Arduino Playground - InterfacingWithHardware
The Mozzi library pushes the normal Arduino to the limit : Mozzi

You might try using interrupts to create more accurate outputs. You can play with prescallers etc. to get a pretty good range of frequencies and interrupts should be considerably more accurate than delay functions as they rely on hardware timers.

Not sure if Tone library uses interrupts it may do that in which case using the Tone library should be fine too.

Lemur:
For reference, here is the code I used.

int speaker = 12;

void setup() {
  pinMode(speaker, OUTPUT);
}
void loop() {
  digitalWrite(speaker, HIGH);
  delay(2.272);
  digitalWrite(speaker, LOW);
  delay(2.272);
}





int speaker = 12;
void setup() {
  pinMode(speaker, OUTPUT);
}
void loop() {
  digitalWrite(speaker, HIGH);
  delay(1.136);
  digitalWrite(speaker, LOW);
  delay(1.136);
}

delay() doesn't accept floating point values...