Path: csiph.com!eternal-september.org!reader02.eternal-september.org!.POSTED!not-for-mail From: Tim Rentsch Newsgroups: comp.lang.c++ Subject: Re: C++ (and some C) quiz questions Date: Thu, 19 May 2022 08:21:39 -0700 Organization: A noiseless patient Spider Lines: 117 Message-ID: <86y1yx1rb0.fsf@linuxsc.com> References: <87czgcqxgc.fsf@bsb.me.uk> <86o7zw2x55.fsf@linuxsc.com> <8635h72bap.fsf@linuxsc.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Injection-Info: reader02.eternal-september.org; posting-host="2a3388073214779a12c7a9c38773b260"; logging-data="13168"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX1/w2PsY8upvXMzjrc6fUR24S0NZJXWrOCA=" User-Agent: Gnus/5.11 (Gnus v5.11) Emacs/22.4 (gnu/linux) Cancel-Lock: sha1:6mjX/kN7/6iUWCYETGp/D89UF6I= sha1:RM8/5hLrHbmA+G4TcjsX1aCHk10= Xref: csiph.com comp.lang.c++:84185 Paavo Helde writes: > 18.05.2022 16:57 Tim Rentsch kirjutas: > >> Manfred writes: >> >>> On 5/18/2022 6:40 AM, Juha Nieminen wrote: >>> >>>> Tim Rentsch wrote: >>>> >>>>> But that doesn't change the problem of potential loss of >>>>> precision, because the representation (and hence the particular >>>>> value) of the constant 0.1 is chosen before that value is >>>>> converted to long double. The constant 0.1, being of type >>>>> double, doesn't have to have less precision than 0.1L, but >>>>> certainly it can. >>>> >>>> AFAIK no C/C++ compiler will second-guess the programmer and assume that >>>> the literal was meant to be a long double literal. If you specify a >>>> literal of type double, the compiler will assume you meant it (and will >>>> just convert it to double without adding any precision to the resulting >>>> value.) >>>> >>>> With double vs. long double the loss in precision isn't extremely >>>> drastic (although in some calculations it could accumulate to significant >>>> proportions). However, people often make the mistake when they are using >>>> some third-party multiple-precision libraries that support floating point >>>> values of arbitrary size. If you are calculating with eg. 1024-bit >>>> floating point, make sure you initialize them properly (ie. do not >>>> initialize such a value with eg. the literal 0.1). >>> >>> I believe Tim was referring to the fact that the standard does not >>> mandate for long double to have more precision than double. >> >> That is one possibility, but I didn't mean just that. >> >> Here is the original context: >> >> long double value = 0.1; >> >> I'm not sure what C++ allows or doesn't allow for the value of >> the literal 0.1. >> >> For C, my understanding is that the current C standard allows the >> constant 0.1 to be represented in the format, and precision, of a >> long double even though its type is double. (The rules for >> floating constants in C has changed over time so I'm not sure if >> that allowance might be different for earlier C standards.) >> >> The next C standard apparently will be explicit on this point - >> in the n2731 draft of the C standard, section 6.4.4.2 paragraph 6 >> says this in part: >> >> The values of floating constants may be represented in >> greater range and precision than that required by the type >> (determined by the suffix); the types are not changed >> thereby. > > Doesn't it just mean that in the program code, one can write the > literal with more precision than needed, just in case the type may > have more precision in another or future implementation? > > const double pi = 3.141592653589793238462643383279502884197; The short answer to this question is no. That seems obvious to me, but let me try to give a more complete explanation. When talking about floating point, the C standard uses the terms range and precision in relation to aspects of elements in the abstract machine. (There are separate notions of "precision" that pertain to integer types or to the *printf() functions, but these uses do not concern us here.) In contrast, a floating constant occurs in program source and is just a sequence of characters. A floating constant has a source form but does not have a range or precision, as the C standard uses those terms. The word "type" is used both to mean a compile-time notion that is manipulated during compilation and to describe an internal format that occurs inside the abstract machine at run time. In many cases these two notions are used interchangeably, but they aren't quite the same, and pointedly so in the case of floating point. For example, in n1570 (a C11 draft), 6.3.1.8 paragraph 2 says this: The values of floating operands and of the results of floating expressions may be represented in greater range and precision than that required by the type; the types are not changed thereby. This sentence illustrates the distinction between "type" as a compile-time notion and a run-time internal format, which may be different than the internal format of the compile-time type. Floating constants have a compile-time type (which is determined by their suffix, or lack thereof). However the type does not necessarily determine the internal format used to represent the constant. Again from n1570, 6.4.4.2 paragraph 5 says in its last sentence: All floating constants of the same source form(75) shall convert to the same internal format with the same value. The footnote numbered 75 gives clarifying examples: 1.23, 1.230, 123e-2, 123e-02, and 1.23L are all different source forms and thus need not convert to the same internal format and value. After reading the above explanation I hope it is clear that the excerpt from n2731 refers to what internal format is used, and does not refer to any aspect of the source form (except of course indirectly because constants having the same source form must use the same internal format and have the same value). Does that make more sense now?