1

Topic: Usage round

My task - to approximate float to int. A question: whether it is possible to use for this purpose std:: round? And if yes, as gets correctly rid of the warning: warning C4244: ' = ': conversion from ' float ' to ' int ', possible loss of data.

2

Re: Usage round

Hello, B0FEE664, you wrote: BFE> My task - to approximate float to int. BFE> the Question: whether it is possible to use for this purpose std:: round? BFE> And if yes as gets correctly rid of the warning: warning C4244: ' = ': conversion from ' float ' to ' int ', possible loss of data. Here a counter that at std:: round type  values the same, as at parameter. Therefore explicit castes to the necessary type it is quite comprehensible, I consider: int value = int (std:: round (3.14f));

3

Re: Usage round

Hello, B0FEE664, you wrote: BFE> My task - to approximate float to int. BFE> the Question: whether it is possible to use for this purpose std:: round? BFE> And if yes as gets correctly rid of the warning: warning C4244: ' = ': conversion from ' float ' to ' int ', possible loss of data. I am normal so I do: double d = 5.5; int i = (int) (d+0.5); for negative it is necessary to take away, if you want a rounding off to  on the unit

4

Re: Usage round

Hello, rg45, you wrote: R> Here a counter that at std:: round type  values the same, as at parameter. Therefore explicit castes to the necessary type it is quite comprehensible, I consider: R> R> int value = int (std:: round (3.14f)); R> And the warranty of what in value will be 3, instead of 2 is?

5

Re: Usage round

Hello, Marty, you wrote: M> I am normal so I do: M> M> double d = 5.5; M> int i = (int) (d+0.5); M> M> for negative it is necessary to take away, if you want a rounding off to  on the unit Why do not use round?

6

Re: Usage round

Hello, B0FEE664, you wrote: BFE> Why do not use round? 1) the Habit - in its old standard was not, yes I yet did not pass to it. House  on old, and on operation 11 I use, but it is not enough - there under  we write, not especially who too is necessary 2) to Remember that does round, floor etc - in pascal could not But there  not so like simple, it was easier  through these functions to approximate By the way, to you that most not  result, it is better to use lround/llround - they long/long long return

7

Re: Usage round

Hello, B0FEE664, you wrote: BFE> And the warranty of what in value will be 3, instead of 2 is? Well to give warranties I did not risk, but purely empirically problems never arose. It is possible to try to run in a cycle through a message a range int.

8

Re: Usage round

Hello, rg45, you wrote: R> It is possible to try to run in a cycle through a message a range int. Likely wanted to write through all range float/double?

9

Re: Usage round

Hello, pagid, you wrote: R>> It is possible to try to run in a cycle through a message a range int. P> Likely wanted to write through all range float/double? We do not call into question correctness of operation std:: round? Whether In doubt only there will be errors at conversion of result of this function to an integer number.

10

Re: Usage round

Hello, B0FEE664, you wrote: R>> Here a counter that at std:: round type  values the same, as at parameter. Therefore explicit castes to the necessary type it is quite comprehensible, I consider: R>> R>> int value = int (std:: round (3.14f)); R>> BFE> And the warranty of what in value will be 3, instead of 2 is? Only for rather small numbers. (1ull <<std:: numeric_limits <Real>:: digits) + 1 - the first which has no faithful representation in real type Real. To it and similar to it to numbers of value of real type cannot be approximated. For float number of significant figures of a mantissa equally 23 + 1 = 24, therefore the boundary "good" number (which the continuous sequence of integer numbers is completed, representable type float) will be equal 16.777.216. For double number of significant figures in a mantissa - 52 + 1 = 53, boundary number - 9.007.199.254.740.992. The checkout code: #include <iostream> #include <iomanip> #include <type_traits> #include <limits> #include <string> #include <locale> class number_punctuation_with_digit_separators final: public std:: numpunct <char> {protected: virtual char do_thousands_sep () const override {return '. ';} virtual std:: string do_grouping () const override {return "\03";}}; template <typename Real, typename Integer> void print_numbers_near_real_boundary_value (const std:: make_signed_t <Integer> limit, const std::string& real_name, const std::string& integer_name) {constexpr auto real_digits = std:: numeric_limits <Real>:: digits; constexpr auto integer_digits = std:: numeric_limits <Integer>:: digits; static_assert (real_digits + 1 <= integer_digits, "The ' Integer ' type is too short to hold the ' Real ' boundary value." ); const auto print_type_line = [] (const auto& type_category, const auto& type_name, const auto& digits) {std:: cout <<std:: left <<std:: setw (10) <<type_category <<std:: setw (12) <<type_name <<std:: right <<std:: setw (9) <<digits <<std:: endl;}; print_type_line ("Type", "Type name", "Digits"); print_type_line ("Real", real_name, real_digits); print_type_line ("Integer", integer_name, integer_digits); std:: cout <<std:: endl; const auto print_number_line = [] (const auto& shift, const auto& initial_integer, const auto& real, const auto& transformed_integer, const auto& are_equal) {std:: cout <<std:: setw (5) <<shift <<std:: setw (24) <<initial_integer <<std:: setw (24) <<real <<std:: setw (24) <<transformed_integer <<std:: setw (9) <<are_equal <<std:: endl;} ; constexpr auto boundary_value = static_cast <Integer> (1) <<real_digits; print_number_line ("Shift", "Initial integer", "Real", "Transformed integer", "Equal?"); for (auto shift = - limit; shift <= limit; ++ shift) {const auto initial_integer = boundary_value + shift; const auto real = static_cast <Real> (initial_integer); const auto transformed_integer = static_cast <Integer> (real); const auto are_equal = (initial_integer == transformed_integer)? "yes": "no"; print_number_line (shift, initial_integer, real, transformed_integer, are_equal);} std:: cout <<std:: endl <<std:: endl;} #define PRINT_NUMBERS_NEAR_REAL_BOUNDARY_VALUE (Real, Integer, limit) \print_numbers_near_real_boundary_value<Real, Integer> (limit, #Real, #Integer) int main () {std:: cout.imbue (std:: locale (std:: locale:: classic (), new number_punctuation_with_digit_separators)); std:: cout <<std:: fixed <<std:: setprecision (0); constexpr auto limit = 10; PRINT_NUMBERS_NEAR_REAL_BOUNDARY_VALUE (float, std:: int32_t, limit); PRINT_NUMBERS_NEAR_REAL_BOUNDARY_VALUE (double, std:: int64_t, limit);} Output: Type Type name Digits Real float 24 Integer std:: int32_t 31 Shift Initial integer Real Transformed integer Equal? -10 16.777.206 16.777.206 16.777.206 yes-9 16.777.207 16.777.207 16.777.207 yes-8 16.777.208 16.777.208 16.777.208 yes-7 16.777.209 16.777.209 16.777.209 yes-6 16.777.210 16.777.210 16.777.210 yes-5 16.777.211 16.777.211 16.777.211 yes-4 16.777.212 16.777.212 16.777.212 yes-3 16.777.213 16.777.213 16.777.213 yes-2 16.777.214 16.777.214 16.777.214 yes-1 16.777.215 16.777.215 16.777.215 yes 0 16.777.216 16.777.216 16.777.216 yes 1 16.777.217 16.777.216 16.777.216 no 2 16.777.218 16.777.218 16.777.218 yes 3 16.777.219 16.777.220 16.777.220 no 4 16.777.220 16.777.220 16.777.220 yes 5 16.777.221 16.777.220 16.777.220 no 6 16.777.222 16.777.222 16.777.222 yes 7 16.777.223 16.777.224 16.777.224 no 8 16.777.224 16.777.224 16.777.224 yes 9 16.777.225 16.777.224 16.777.224 no 10 16.777.226 16.777.226 16.777.226 yes Type Type name Digits Real double 53 Integer std:: int64_t 63 Shift Initial integer Real Transformed integer Equal? -10 9.007.199.254.740.982 9.007.199.254.740.982 9.007.199.254.740.982 yes-9 9.007.199.254.740.983 9.007.199.254.740.983 9.007.199.254.740.983 yes-8 9.007.199.254.740.984 9.007.199.254.740.984 9.007.199.254.740.984 yes-7 9.007.199.254.740.985 9.007.199.254.740.985 9.007.199.254.740.985 yes-6 9.007.199.254.740.986 9.007.199.254.740.986 9.007.199.254.740.986 yes-5 9.007.199.254.740.987 9.007.199.254.740.987 9.007.199.254.740.987 yes-4 9.007.199.254.740.988 9.007.199.254.740.988 9.007.199.254.740.988 yes-3 9.007.199.254.740.989 9.007.199.254.740.989 9.007.199.254.740.989 yes-2 9.007.199.254.740.990 9.007.199.254.740.990 9.007.199.254.740.990 yes-1 9.007.199.254.740.991 9.007.199.254.740.991 9.007.199.254.740.991 yes 0 9.007.199.254.740.992 9.007.199.254.740.992 9.007.199.254.740.992 yes 1 9.007.199.254.740.993 9.007.199.254.740.992 9.007.199.254.740.992 no 2 9.007.199.254.740.994 9.007.199.254.740.994 9.007.199.254.740.994 yes 3 9.007.199.254.740.995 9.007.199.254.740.996 9.007.199.254.740.996 no 4 9.007.199.254.740.996 9.007.199.254.740.996 9.007.199.254.740.996 yes 5 9.007.199.254.740.997 9.007.199.254.740.996 9.007.199.254.740.996 no 6 9.007.199.254.740.998 9.007.199.254.740.998 9.007.199.254.740.998 yes 7 9.007.199.254.740.999 9.007.199.254.741.000 9.007.199.254.741.000 no 8 9.007.199.254.741.000 9.007.199.254.741.000 9.007.199.254.741.000 yes 9 9.007.199.254.741.001 9.007.199.254.741.000 9.007.199.254.741.000 no 10 9.007.199.254.741.002 9.007.199.254.741.002 9.007.199.254.741.002 yes Therefore if it would be desirable absolutely reliable rounding off, is better to write over std:: round which would lead necessary check of possibility of a correct rounding off (this wrapper it is possible to make a wrapper sample, parametrizing integral type to which should be the result of performance std:: round) is resulted.

11

Re: Usage round

Hello, Constructor, you wrote: R>>> Here a counter that at std:: round type  values the same, as at parameter. Therefore explicit castes to the necessary type it is quite comprehensible, I consider: R>>> R>>> int value = int (std:: round (3.14f)); R>>> BFE>> And the warranty of what in value will be 3, instead of 2 is? A C> Only for rather small numbers. (1ull <<std:: numeric_limits <Real>:: digits) + 1 - the first which has no faithful representation in real type Real. To it and similar to it to numbers of value of real type cannot be approximated. A C> For float number of significant figures of a mantissa equally 23 + 1 = 24, therefore the boundary "good" number (which the continuous sequence of integer numbers is completed, representable type float) will be equal 16.777.216. These reasonings, are is finite true and on their base we can draw an output, what not any whole can be presented in a type float. In other words, too big loss of accuracy can arise at conversion int-> float. But the question after all now costs about reverse conversion: float-> int: whether can happen so, what at conversion   std:: round (f) to an integer number, the number, not the closest to result of expression will be selected? (Where f has type float and is in a range [std:: numeric_limits <int>:: min (), std:: numeric_limits <int>:: max ()])

12

Re: Usage round

Hello, rg45, you wrote: R> These reasonings, are is finite true and on their base we can draw an output, what not any whole can be presented in a type float. In other words, too big loss of accuracy can arise at conversion int-> float. Precisely! For some reason suddenly climbed up in a head that int -> float somehow can affect on float -> int. R> the Question now costs about reverse conversion: float-> int: whether can happen so, what at conversion   std:: round (float (x)) to an integer number, the number, not the closest to result of expression will be selected? At float -> int then there is then only a danger of an output for representation boundaries int (std:: numeric_limits <int>:: min ()... std:: numeric_limits <int>:: max ()).

13

Re: Usage round

Hello, Marty, you wrote: M> I am normal so I do: M> M> double d = 5.5; M> int i = (int) (d+0.5); M> And how this conversion works? I here not undertake to tell.

14

Re: Usage round

Hello, T4r4sB, you wrote: TB> And how this conversion works? I here not undertake to tell. Perfectly works. And what you confuses?

15

Re: Usage round

Hello, Marty, you wrote: M> Perfectly works. And what you confuses? What exactly does it do? The answer with sending on dock is necessary.

16

Re: Usage round

Hello, T4r4sB, you wrote: M>> Perfectly works. And what you confuses? TB> what exactly it does? The answer with sending on dock is necessary. Without links does not go? Type coercion double to int works as fractional part rejection. It still since pure  so works, for certain is somewhere in the standard beginning, there, where about fundamental types write. 0.5 it is added, that the rounding off was by rules - to the nearest whole. At Straustrupa in old issuing of the beginning of the century in application B.6.2.6 about conversion floating in the whole

17

Re: Usage round

Hello, B0FEE664, you wrote: BFE> My task - to approximate float to int. BFE> the Question: whether it is possible to use for this purpose std:: round? BFE> And if yes as gets correctly rid of the warning: warning C4244: ' = ': conversion from ' float ' to ' int ', possible loss of data. The answer to your question: it is possible, the warning is removed by means of explicit a caste ( or static_cast) more detailed answer here: https://stackoverflow.com/questions/485 … float-in-c in particular, try lround

18

Re: Usage round

Hello, B0FEE664, you wrote: BFE> And the warranty of what in value will be 3, instead of 2 is? About safety a caste to int here: https://stackoverflow.com/questions/471 … m-stdround

19

Re: Usage round

Hello, uzhas, you wrote: U> in particular, try lround

20

Re: Usage round

Hello, Marty, you wrote: M> Without links does not go? Type coercion double to int works as fractional part rejection. It still since pure  so works, for certain is somewhere in the standard beginning, there, where about fundamental types write. 0.5 it is added, that the rounding off was by rules - to the nearest whole. M> at Straustrupa in old issuing of the beginning of the century in application B.6.2.6 about conversion floating in whole Well if so that will be for negative numbers?

21

Re: Usage round

Hello, T4r4sB, you wrote: M>> At Straustrupa in old issuing of the beginning of the century in application B.6.2.6 about conversion floating in whole TB> Well if so that will be for negative numbers? The fractional part, not will be discarded?

22

Re: Usage round

Hello, rg45, you wrote: R>... Therefore explicit castes to the necessary type it is quite comprehensible, I consider: R> R> int value = int (std:: round (3.14f)); R> It unless castes?

23

Re: Usage round

Hello, VladFein, you wrote: R>> R>> int value = int (std:: round (3.14f)); R>> VF> It unless castes? Certainly. Such expressions   "function-style conversions" and they are equivalent "cast expressions": (int) std:: round (3.14f). Here that is told about it in the standard (a C ++ 17): 8.2.3 Explicit type conversion (functional notation) 2 If the initializer is a parenthesized single expression, the type conversion expression is equivalent (in definedness, and if defined in meaning) to the corresponding cast expression (8.4)... And here still the citation from 8.4: 8.4 Explicit type conversion (cast notation) 2 An explicit type conversion can be expressed using functional notation (8.2.3), a type conversion operator (dynamic_cast, static_cast, reinterpret_cast, const_cast), or the cast notation. cast-expression: unary-expression (type-id) cast-expression

24

Re: Usage round

Hello, Marty, you wrote: M>> M>> double d = 5.5; M>> int i = (int) (d+0.5); M>> TB>> Well if so that will be for negative numbers? M> the fractional part, not will be discarded? Here you should agree with it - your variant for negative numbers will work not as it is expected from an arithmetical rounding off. For example, if we  to approximate-2.1 we receive:-2.1->-1.6->-1. That worked as it is necessary, it is necessary slightly : int i = (int) (d <0? d - 0.5: d + 0.5);

25

Re: Usage round

Hello, rg45, you wrote: R> Here you should agree with it - your variant for negative numbers will work not as it is expected from an arithmetical rounding off. For example, if we  to approximate-2.1 we receive:-2.1->-1.6->-1. That worked as it is necessary, it is necessary slightly : R> R> int i = (int) (d <0? d - 0.5: d + 0.5); R> Someone did not read up my message> for negative it is necessary to take away, if want a rounding off to  on the unit