It as good as does.
the fractional part is discarded
(i.e., the value is truncated toward zero)
No, that's not in the Definitions section, nor are the words "fractional
part" italicized: those are the two methods used by the standard to
identify a definition. Therefore:
If that were the case, then that paragraph would be a prime example of
why it's generically a bad idea for the standard to specify something
twice. In reality, your use of the definite article in your phrase "the
mathematical definition" seems to be unjustified - alternative
definitions are in use. One point of view looks at the value that would
print out as "-23.45", and parses it as having a sign factor of -1, an
integer part of 23, a decimal point, and a fractional part of 45/100.
Under that interpretation, "discarding the fractional part" means
converting "-12.34" into "-12.", and is indeed equivalent to truncation
toward zero. Therefore, this isn't a double specification; the
truncation clause clarifies which one of the multiple definitions
currently in use for "fractional part" is being used in the discard clause.
You introduce correctness. For the record, I am not at all
interested in correctness here. Good definitions are a
result of much thought and work.
The only thing being defined here is the behavior, not the meaning of
the terms used in that definition. You're right about good definitions,
but one of requirements for a good definition, one of the reasons it
requires careful thought, is that all of the terms used in that
definition should be used correctly.
Presumably truncating toward zero in the C standard
is to reduce the number of cases where conversion leads to overflow.
I can't be sure what the reason was. Personally, I've never written code
where truncation of negative numbers toward zero was the desired
behavior. In most cases when I've converted a floating point number that
might be negative to an integer, what I wanted was lrint(x) (but
instead, I had to settle for (long)floor(x+0.5), because our contract
with our client requires use of C90 code); the second most common thing
I've wanted is (long)floor(x) - I can't remember ever wanting the result
that I would have gotten for negative values of x from (long)x.
The Rationale only says "There was strong agreement in the C89 Committee
that floating values should truncate toward zero
when converted to an integer type, the specification adopted in the
Standard. Although K&R 35 permitted negative floating values to truncate
away from zero, no C89 Committee member knew of an implementation that
functioned in such a manner.2"
Footnote 2 says "The Committee has since learned of one such
implementation."