- rational numbers - 23 Updates
- Memory allocator - 1 Update
- "C++20 Coroutines" by Martin Bond - 1 Update
| Branimir Maksimovic <branimir.maksimovic@gmail.com>: Sep 23 11:47PM > being read > * If fewer than 3 items are present on a line, then it apparently hangs, > with no explanation, waiting for them on the next line streams are for serialization, getline is for user input. -- 7-77-777 \|/ --- /|\ -- Evil Sinner! |
| Keith Thompson <Keith.S.Thompson+u@gmail.com>: Sep 23 04:56PM -0700 > On 23/09/2021 21:48, Ian Collins wrote: >> On 24/09/2021 02:02, Bart wrote: [...] > out. But here's a summary of issues with the C++ loop: > * It's not line-oriented; the new lines get out of sync with the data > being read Right, it's not designed to be. For example: int a, b, c; std::cin >> a >> b >> c; std::cout << "a=" << a << " b=" << b << " c=" << c << '\n'; The std::cin line reads integer values, skipping white space (which includes newlines) before each. If you just want to skip white space other than newlines, there's probably a way to do that. If you want line-oriented input, read a line at a time using std::getline() and then parse each line. It's not that hard. std::string line; std::getline(std::cin, line); std::stringstream ss(line); ss >> a >> b >> c; > * If fewer than 3 items are present on a line, then it apparently > hangs, with no explanation, waiting for them on the next line Because it's not line-oriented. > next line. So if 400 and 500 are extra items, and the user enters 10 > 20 30 on the next line, if will read '400 500 10', with 20 and 30 > rolled over to the subsequent line Because it's not line-oriented. > * If more than 3 extra items are present, then on the next iteration, > it doesn't wait for user input at all. If will not do so until > everything on that initial line is consumed Because it's not line-oriented. > * Numeric separators within numbers such as "_" and "'" are not > recognised, and cause an error Right. Just how permissive do you think it should be? > * Numbers which are quoted are not recognised, and cause an error Right. 123 is a number; "123", "123", '123', and «123» are not. > * Separators between numbers other than white space are not > recognised, such as commas, and cause an error Right. > * Floating point numbers (using "." and/or "e") are not recognised; > those characters cause an error Right. You can read into a floating-point object if you want to support floating-point syntax. > * When an out-of-range number is entered, it reads i32.max (etc) for > that number, but also generates an error Yes, and? > zeros, so it never consumes the rest of the line. So in a loop, it > just prints zeros over and over again without the user entering > anything. It's difficult to respond to that without an example. [...] -- Keith Thompson (The_Other_Keith) Keith.S.Thompson+u@gmail.com Working, but not speaking, for Philips void Void(void) { Void(); } /* The recursive call of the void */ |
| Bart <bc@freeuk.com>: Sep 24 01:58AM +0100 On 24/09/2021 00:56, Keith Thompson wrote: > std::getline(std::cin, line); > std::stringstream ss(line); > ss >> a >> b >> c; Thanks at last somebody posted some actual code instead of just saying how easy it was. But a couple of things: * (It needs #include <sstream>) * If I put this in my loop, and type 10 20 30 on the first line, it prints 10 20 30; that's fine. * But if I type only 40 on the next line, it prints 40 20 30. So if there are fewer entries than expected, it will not do '>> b >> c'; those values are unchanged from before. * It's better behaved as it doesn't try to exhaust the same line over again. But if the input is '10.2 11 12', the output is '10 0 999'. (The 999 is what I've now initialised a,b,c to at the start of each loop.) > Because it's not line-oriented. > Because it's not line-oriented. > Because it's not line-oriented. Isn't that what I said? >> * Numeric separators within numbers such as "_" and "'" are not >> recognised, and cause an error > Right. Just how permissive do you think it should be? For interactive user input - quite permissive. People are quite likely to type in decimal points or do unexpected things. A full treatment is hard, but if someone types "100." or 1e2 instead of "100", should that be a hanging offence? >> * Numbers which are quoted are not recognised, and cause an error > Right. 123 is a number; "123", "123", '123', and «123» are not. If you are reading CSV files and such, fields are sometimes enclosed in quotes, including numeric fields. >> * When an out-of-range number is entered, it reads i32.max (etc) for >> that number, but also generates an error > Yes, and? That error is the problem. >> just prints zeros over and over again without the user entering >> anything. > It's difficult to respond to that without an example. I thought I posted it earlier. Here's the code: #include <iostream> int main() { int a,b,c; int x=0; do { std::cout << "Prompt> "; std::cin >> a >> b >> c; std::cout << a << " " << b << " " << c << "\n"; } while (++x<10); } And here it is in action; the only input I type in is the '10.2 11 12' line, the rest just keeps going, and only stops because I cap the output at 10 lines: C:\c>a Prompt> 10.2 11 12 10 0 0 Prompt> 10 0 0 Prompt> 10 0 0 Prompt> 10 0 0 Prompt> 10 0 0 Prompt> 10 0 0 Prompt> 10 0 0 Prompt> 10 0 0 Prompt> 10 0 0 Prompt> 10 0 0 |
| Branimir Maksimovic <branimir.maksimovic@gmail.com>: Sep 24 01:40AM int main() { string line = "GeeksForGeeks is a must try"; // Vector of string to save tokens vector <string> tokens; // stringstream class check1 stringstream check1(line); string intermediate; // Tokenizing w.r.t. space ' ' while(getline(check1, intermediate, ' ')) { tokens.push_back(intermediate); } // Printing the token vector for(int i = 0; i < tokens.size(); i++) cout << tokens[i] << '\n'; } -- 7-77-777 \|/ /|\ -- Evil Sinner! |
| Keith Thompson <Keith.S.Thompson+u@gmail.com>: Sep 23 07:35PM -0700 > Thanks at last somebody posted some actual code instead of just saying > how easy it was. But a couple of things: > * (It needs #include <sstream>) Yes? > * But if I type only 40 on the next line, it prints 40 20 30. So if > there are fewer entries than expected, it will not do '>> b >> c'; > those values are unchanged from before. My quick and dirty code sample didn't check for errors. The user didn't provide inputs for those values. What exactly do you expect to happen? You can query ss.good(), ss.bad(), ss.fail(), and ss.eof() to see whether the input operation succeeded. >> Because it's not line-oriented. >> Because it's not line-oriented. > Isn't that what I said? My point is that you complained that it's not line-oriented (which is a deliberate design decision) and then complained about the inevitable consequences of the fact that it's not line-oriented. > to type in decimal points or do unexpected things. A full treatment is > hard, but if someone types "100." or 1e2 instead of "100", should that > be a hanging offence? Hanging offence? Give me a freaking break. Numeric input has to define *some* syntax. If you want a different syntax, implement it. That includes deciding what an integer should be set to if the input is "1.5". If you like, read it into a string and try converting that string to whatever you want. The default input for numeric input is reasonably simple and straightforward. >>> that number, but also generates an error >> Yes, and? > That error is the problem. What? You're not suggesting that it should set the value to INT_MAX *and then not give any indication that there was a problem*, are you? > Prompt> 10 0 0 > Prompt> 10 0 0 > Prompt> 10 0 0 The first << operation succeeded, set a to 10, and consumed the characters '1' and '0'. The second one failed because it was trying to read an integer value and saw a '.' character. Try reading an integer again, and it fails again. If you instead tried to read a string or a character, it would consume the '.' character and whatever follows it. If you want to consume and discard incorrect input rather than letting it remain in the input stream, you can do that by writing different code. If you do something simple like `std::cin >> a >> b >> c`, it doesn't give you a way to determine which input operation failed -- but you can tell whether they were all successful or not. Sometimes that's good enough. If it isn't, write different code. -- Keith Thompson (The_Other_Keith) Keith.S.Thompson+u@gmail.com Working, but not speaking, for Philips void Void(void) { Void(); } /* The recursive call of the void */ |
| Juha Nieminen <nospam@thanks.invalid>: Sep 24 04:37AM >> type should get an std::ostream (or FILE*, or whatever) that it >> can use to directly write whatever it wants there. > Why? Is this just because of memory overhead concerns? What is this sudden strange attitude of "efficiency doesn't matter"? This is C++ we are talking about, not Python, or JavaScript, or PHP, or a shell script. The very reason why std::ostream uses operator overloading to become extensible to custom types is that it allows these custom types to output their data in any way they want, using the std::ostream object. If the custom type in question is a list of a million objects, you don't need to allocate and construct a string containing the textual representation of these million objects (the length of the string not even necessarily being known in advance, requiring multiple reallocations), then the string printed, and then the string destroyed... only to immediately doing the exact same thing again with another object (or, heck, with the same object). The operator overloading allows for the object to output one element at a time, without the overhead of constructing a gigantic string, using multiple reallocations. If an alternative to operator overloading is suggested, that alternative shouldn't be worse in terms of performance (and, preferably, not any more difficult to use). If someone says "using operator<< for this is horrible", then by all means suggest a better alternative, not a worse one. A "tostring()" method is *most definitely* a worse one. |
| Juha Nieminen <nospam@thanks.invalid>: Sep 24 04:38AM >> add support to the standard printing function for your type. > I'm not forcing anything at all. Custom types can have dedicated > tostring routines; or use default ones; or have nothing. Then how exactly do you add support for your type into the standard printing function, if not by forcing your type to have a "tostring" method? |
| alessandro volturno <alessandro.volturno@libero.it>: Sep 24 09:45AM +0200 Il 23/09/2021 16:38, Siri Cruise ha scritto: > that fills add/subtract loss of signficance with random bits. > That will form a basis for happy numbers, sad numbers, and angry > numbers, and more generally, emotional numbers. I've never heard about erratic or emotional numbers. Is it a joke or a strange application in mathematical field? Could you please give me an example of use, so to make understanding easier? Thank you |
| Branimir Maksimovic <branimir.maksimovic@gmail.com>: Sep 24 07:46AM I realy like to_string, to me it is *very usefull* and use it often since then. -- 7-77-777 \|/ --- /|\ -- Evil Sinner! |
| Branimir Maksimovic <branimir.maksimovic@gmail.com>: Sep 24 07:50AM I beleive it is joke :P But in math you can define ANY set, that follow rules of ALGEBRA :P group, semigroup, ring, field.... -- 7-77-777 \|/ --- /|\ -- Evil Sinner! |
| David Brown <david.brown@hesbynett.no>: Sep 24 10:58AM +0200 On 24/09/2021 09:45, alessandro volturno wrote: > strange application in mathematical field? > Could you please give me an example of use, so to make understanding > easier? It is a joke. There are lucky numbers, perfect numbers, practical numbers, fortunate numbers, untouchable numbers, weird numbers, polite numbers, and extravagant numbers. But no emotional numbers, that I am aware of. These are all integer sequences or subsets, and thus don't need any special new arithmetic. If you want to have other number types that could have C++ classes with operators, you could try Gaussian integers, algebraic numbers, constructable numbers, computable numbers, transfinite numbers, hyperreals, surreals, etc. Or you can support all kinds of constructed algebraic structures. GF(2⁸) is a nice one to play with, and has practical applications (it is the basis for most RAID6 implementations). |
| HorseyWorsey@the_stables.com: Sep 24 09:12AM On Thu, 23 Sep 2021 18:31:34 +0100 >The support needed is not significant. My proof-of-concept to add >automatic printf format codes to a C compiler (so you do "%?" for any >basic type instead of "%d" etc), was 50 lines of code. And no doubt requires the resulting binary to store a boatload of RTTI in order to do that which rather defeats the point of using C which is to create slimline efficient binaries. It could have been done for C++ which has RTTI anyway but stroustrup went with iostream instead. >javascript. >So. why bother with even std::cout (I still don't know what that >actually is) or printf? Just have fgetc and fputc. As you well know the point of cout is to allow output of complex objects which have overloaded << without having to call a converter function first. If all you're doing is outputting formatted strings then IMO *printf() is a better choice because its more expressive and compact. >After all how hard can it be to knock up an int-to-string converter? The A universal number to string converter is actually quite complex as it has to deal with IEEE 754 floating point format not to mention negative numbers and formatting. |
| Paavo Helde <myfirstname@osa.pri.ee>: Sep 24 12:17PM +0300 24.09.2021 07:37 Juha Nieminen kirjutas: > What is this sudden strange attitude of "efficiency doesn't matter"? > This is C++ we are talking about, not Python, or JavaScript, or PHP, > or a shell script. It appears we are both concerned about efficiency. Alas, we have drastically different opinions about where the inefficiencies lure. Fortunately programming is strongly connected to reality, unlike some other areas of human activity, so one can check the reality to see what's really happening. Here is a test program measuring the two different approaches to streaming: (A) sending 100 million ints to std::ostream separately, and (B) formatting them first into a huge std::string, then sending that to std::ostream in one go. My results are here: MSVC++ 2019 x64 Release (/O2 optimization): Traditional streaming: 28561 ms to_string() streaming: 2663 ms to_string() is 10.7251 times faster than traditional streaming. To be honest, g++ 8.3 on Linux (or more exactly, libstdc++) seems to be much better with iostreams, but still to_string() beats iostreams: $ g++ -Wall -O2 test5.cpp -std=c++17 $ ./a.out Traditional streaming: 4268 ms to_string() streaming: 2592 ms to_string() is 1.6466 times faster than traditional streaming. Source code: #include <iostream> #include <string> #include <sstream> #include <vector> #include <numeric> #include <charconv> #include <chrono> #include <cstdint> class A { public: A(); // traditional operator<< friend std::ostream& operator<<(std::ostream& os, const A& a); // tostring() operator std::string to_string() const; private: std::vector<int> data; }; A::A() { // Initialize data to something data.resize(100000000); std::iota(data.begin(), data.end(), 0); } std::ostream& operator<<(std::ostream& os, const A& a) { for (auto& x: a.data) { os << x << ' '; } return os; } std::string A::to_string() const { const size_t k = 64; char buffer[k]; std::string result; for (auto x: data) { auto q = std::to_chars(buffer+0, buffer+k, x, 10).ptr; *q++ = ' '; result.append(buffer, q-buffer); } return result; } using sclock = std::chrono::steady_clock; std::int64_t ms(sclock::duration lapse) { return std::chrono::duration_cast<std::chrono::milliseconds>(lapse).count(); } int main() { std::ostringstream sink1, sink2; A a; // traditional streaming sclock::time_point start1 = sclock::now(); sink1 << a; sclock::time_point finish1 = sclock::now(); std::cout << "Traditional streaming: " << ms(finish1-start1) << " ms\n"; // tostring() sclock::time_point start2 = sclock::now(); sink2 << a.to_string(); sclock::time_point finish2 = sclock::now(); std::cout << "to_string() streaming: " << ms(finish2-start2) << " ms\n"; double ratio = double(ms(finish1-start1))/ms(finish2-start2); std::cout << "to_string() is " << ratio << " times " << (ratio>1.0 ? "faster" : "slower") << " than traditional streaming.\n"; // Make use of the results to ensure these were not optimized away. return int(sink1.str().size()-sink2.str().size()); } |
| Ian Collins <ian-news@hotmail.com>: Sep 24 09:37PM +1200 On 23/09/2021 00:45, Bart wrote: > The question posed was whether turning into individual print items into > a string object, before sending that string to the output, was a > significant overhead. The answer is in comparison with doing the actual output, no. > I showed my /dynamic/ code wasn't significantly slower than C++ > (actually it was faster) despite doing those conversions, plus a whole > bunch of other overheads that C++ will not have. What you showed is the implementation you are using is really really (10x slower than my unimpressive laptop) slow! - Ian. |
| Ian Collins <ian-news@hotmail.com>: Sep 24 09:45PM +1200 On 20/09/2021 17:20, Juha Nieminen wrote: > after use (because in many cases you will need to create a dynamically > allocated string in order to contain the textual representation of the value > of the object you are trying to print). The whole to_string() concept also falls apart if you are printing in a template. int.to_string() anyone? -- Ian. |
| Siri Cruise <chine.bleu@yahoo.com>: Sep 24 02:48AM -0700 In article <sik3v7$2av$1@dont-email.me>, > numbers, fortunate numbers, untouchable numbers, weird numbers, polite > numbers, and extravagant numbers. But no emotional numbers, that I am > aware of. I think erratic numbers would be a good lesson. People have the illusion that losing almost all bits in a subtraction does not result in the loss of precision. The CDC Star-100 had something similar and it really peeved off customers. They didm't want to ne reminded that all their displays of real number fractions were meaningless. Introducing random bits instead of zeros when normalising differences would visibly change output on each run for numerically unstable code. -- :-<> Siri Seal of Disavowal #000-001. Disavowed. Denied. Deleted. @ 'I desire mercy, not sacrifice.' /|\ Discordia: not just a religion but also a parody. This post / \ I am an Andrea Doria sockpuppet. insults Islam. Mohammed |
| Bart <bc@freeuk.com>: Sep 24 11:15AM +0100 On 24/09/2021 05:38, Juha Nieminen wrote: > Then how exactly do you add support for your type into the standard > printing function, if not by forcing your type to have a "tostring" > method? I've lost track of what you're asking. But if there is really a need to convert of value of some abstract type T into a sequenct of characters, then how else can be it done other than providing support functions which does that conversion? If your quibble about having to do the whole conversion into some intermediate string before starting to output characters from that new string, rather than do it a character at a time? I'm sure, it's possible to that that conversion incrementally, to provide that conversion in the form of a generator function, which yields the next character (not sure what C++ capabilities are here). Or to provide a callback function to the translation function to tell it what to do with each new generated character. Although both of sound a lot less efficient to me. Probably 99% of all print items would have an intermediate string less than 100 characters along, so that a simple fixed buffer would suffice. That's a better idea than sending a character at time to some stream-processing function (like fputc). |
| Branimir Maksimovic <branimir.maksimovic@gmail.com>: Sep 24 10:19AM Efficincy in IO is not issue as IO itself is SLOW. Also ALGORITHM is WHAT COUNTS, this is how HUMANS can always BEAT compilers. -- 7-77-777 \|/ /|\ -- Evil Sinner! |
| Bart <bc@freeuk.com>: Sep 24 12:10PM +0100 > And no doubt requires the resulting binary to store a boatload of RTTI in order > to do that which rather defeats the point of using C which is to create > slimline efficient binaries. Huh? This tweak to C means that when somebody writes: printf("%? %?", i, f); it converts the string to "%d %f". There is zero impact on any binaries. >> actually is) or printf? Just have fgetc and fputc. > As you well know the point of cout is to allow output of complex objects > which have overloaded << without having to call a converter function first. Actually no I don't. I'm still not entirely clear how << works, other than it is 100% unintuitive. Virtually all output I want to do is of standard types. It would just be nice to output A and B by writing: ... A, B ... rather than: ... A << " " << B ... I'm just surprised you don't have to type: ... A std::<< " " std::<< B ... > If all you're doing is outputting formatted strings then IMO *printf() is a > better choice because its more expressive and compact. Yeah. It takes a lot to suddenly make printf seem much better! > A universal number to string converter is actually quite complex as it has to > deal with IEEE 754 floating point format not to mention negative numbers and > formatting. Negative numbers aren't that difficult actually... |
| Branimir Maksimovic <branimir.maksimovic@gmail.com>: Sep 24 11:23AM For example of type safe print take a look at Bjarne's BOOK. -- 7-77-777 \|/ --- /|\ -- Evil Sinner! |
| HorseyWorsey@the_stables.com: Sep 24 03:19PM On Fri, 24 Sep 2021 12:10:01 +0100 >Huh? This tweak to C means that when somebody writes: > printf("%? %?", i, f); >it converts the string to "%d %f". There is zero impact on any binaries. And what happens if 'i' is a char? Do you want %c, %d or %u? What if its a pointer? Do you want %p, %x, %X, %lu etc? >> which have overloaded << without having to call a converter function first. >Actually no I don't. I'm still not entirely clear how << works, other >than it is 100% unintuitive. So you're complaining about basic C++ functionality you don't even understand. Got it. > ... A, B ... >rather than: > ... A << " " << B ... Whats special about a space? What if someone wants 2 spaces as a seperator or maybe a tab or comma? C++ is a professional language, its not BASIC for kiddies to output simple tabular results. Plus a comma already has syntactic meaning in C & C++. >> deal with IEEE 754 floating point format not to mention negative numbers and >> formatting. >Negative numbers aren't that difficult actually... So long as you remember chars,ints etc are 2's complement whereas floating point uses a sign bit. |
| "daniel...@gmail.com" <danielaparker@gmail.com>: Sep 24 08:59AM -0700 On Friday, September 24, 2021 at 3:46:49 AM UTC-4, Branimir Maksimovic wrote: > I realy like to_string, to me it is *very usefull* and use it often > since then. It's inherently inefficient though, particularly as it's frequently used to append a small piece of text to a larger string, repeated many times. Thus are many copies created. Daniel |
| "daniel...@gmail.com" <danielaparker@gmail.com>: Sep 24 09:07AM -0700 On Thursday, September 23, 2021 at 10:35:44 PM UTC-4, Keith Thompson wrote: > give you a way to determine which input operation failed -- but you can > tell whether they were all successful or not. Sometimes that's good > enough. If it isn't, write different code. I see `std::cout << a` in real code, but I don't see `std::cin >> a >> b >> c` in anything other than toy examples. If we have something, we can send that to `std::cout` without worrying about it, but input invariably has to be validated. Daniel |
| scott@slp53.sl.home (Scott Lurndal): Sep 24 02:58PM >variant of `malloc` while the client code, the app, uses another. >I believe, but please correct me if I'm wrong, that you can't do that >with a Unix shared library? For every symbol declared as "weak" there is a corresponding "strong" symbol which starts with an underscore. The dynamic shared object (dso) can use the strong version if it wishes to prevent the application from overriding its malloc function. (or read, or write, or lseek, etc). |
| Juha Nieminen <nospam@thanks.invalid>: Sep 24 04:42AM >>jumps wherever the processing was going on at that moment, based on those >>state variables? > Yes. Then I don't know what to say. Rather than perhaps question your sanity. |
| You received this digest because you're subscribed to updates for this group. You can change your settings on the group membership page. To unsubscribe from this group and stop receiving emails from it send an email to comp.lang.c+++unsubscribe@googlegroups.com. |
No comments:
Post a Comment