Well, in that
case, R
(silently!) uses the modified form
$$
R_0^2 = 1 - \frac{\sum_i (y_i - \hat y_i)^2}{\sum_i y_i^2} \>.
$$$$
R_0^2 = \frac{\sum_i \hat y_i^2}{\sum_i y_i^2} = 1 - \frac{\sum_i (y_i - \hat y_i)^2}{\sum_i y_i^2} \>.
$$
It helps to recall what $R^2$ is trying to measure. In the former
case, it is comparing your current model to the reference
model that only includes an intercept (i.e., constant term). In the
second case, there is no intercept, so it makes little sense to
compare it to such a model. So, instead, $R_0^2$ is computed, which
implicitly uses as a reference model corresponding to noise only.
In what follows below, I focus on the second expression for both $R^2$ and $R_0^2$ since that expression generalizes to other contexts and it's generally more natural to think about things in terms of residuals.
But, how are they different, and when?
Let's take a brief digression into some linear algebra and see if we
can figure out what is going on. First of all, let's call the fitted
values from the model with intercept as $\newcommand{\yhat}{\hat
{\mathbf y}}\newcommand{\ytilde}{\tilde {\mathbf y}}\yhat$ and the
fitted values from the model without intercept $\ytilde$.
Ok, so how do we make the ratio on the left-hand side small. Well,Ok, so how do we make the ratio on the left-hand side small?
Recall that
$\newcommand{\P}{\mathbf P}\ytilde = \P_0 \y$ and $\yhat = \P_1 \y$ where $\P_0$ and $\P_1$ are
projection matrices corresponding to subspaces $S_0$ and $S_1$ such
that $S_0 \subset S_1$.
Here we try to generate an example close to the case in the
question wherewith an intercept is explicitly in the model and which behaves close to the case in the question. Below is some simple R
code to demonstrate.
set.seed(.Random.seed[1])
n <- 220
a <- 0.5
b <- 0.5
se <- 0.25
# Make sure x has a strong mean offset
x <- rnorm(n)/3 + a
y <- a + b*x + se*rnorm(x)
int.lm <- lm(y~x)
noint.lm <- lm(y~x+0)
# For comparison to summary(.) output
rsq.int <- cor(y,x)^2
rsq.noint <- 1-mean((y-noint.lm$fit)^2) / mean(y^2)