Home  Forums  Reviews  Guides  Newsgroups  Register  Search 
Thread Tools 
David Hutto 


 
Seebs
Guest
Posts: n/a

On 20110120, David Hutto <(EMail Removed)> wrote:
>> For a specific example, if something looks like homework, most experienced >> programmers will conclude that, though the STATED problem was "I want someone >> to do this for me", the REAL problem is "I need to learn how to do this so >> I can not just get a passing grade but get one honestly". > But this is assuming that all individuals here that ask a basic > question are in school. No, it isn't. I didn't state that "basic questions" were the same category as "looks like homework". > We're all self learners, even when in class we > have to comprehend the outer layers of education in the current > curriculum. So don't always assume a basic question is 'school' level, > when it might be just 'tutorial' level. Right... >> That said, I didn't think the original looked like homework. See? Not all newbie questions look like homework. In fact, in my experience, not that many do; homework problems have a characteristic artificiality to them, in that they're built around a result you can easily verify without using the computer, rather than something you'd actually need a computer to do. s  Copyright 2010, all wrongs reversed. Peter Seebach / http://www.velocityreviews.com/forums/(EMail Removed) http://www.seebs.net/log/ < lawsuits, religion, and funny pictures http://en.wikipedia.org/wiki/Fair_Game_(Scientology) < get educated! I am not speaking for my employer, although they do rent some of my opinions. 




Seebs 


 
Bartc
Guest
Posts: n/a

"pozz" <(EMail Removed)> wrote in message news:ihack6$1go$(EMail Removed)... > Il 20/01/2011 11:46, Mark Bluemel ha scritto: >> I find the basic idea below easier to comprehend. I haven't tried to >> achieve all you have, but I think the idea is clear enough and could >> be extended to do what you want. > > [...] > > This an interesting approach, but I couldn't find how I can achieve the > zeropadding, the sign printing and the custom width. > > Also the split() function uses many divisions and multiplications in > cycles (these are time consuming operations). > I'd like to call just the sprintf() to have all the digits in textual form > and operate only character shifting or similar things. You might find that sprintf() also uses division internally. You're making things a little harder (IMO) by using the Cstyle format specification for sprintfnum(). This is fiddly to decipher. Perhaps forget that to start with (it can be bolted on later), and concentrate on the 3 parameters that the format would yield: Width, Leadingzeros, and Plussign (W,Z and P) You apply sprintf() (or even itoa()) to the data x, to give a string, and then there is div, effectively a fourth parameter (DP), which just gives the offset of the decimal point within that string. Now the logic is a bit simpler: apply W, Z, P and DP to the plain string version of x. This is not exactly trivial yet, depending on how many things you want to take care of (what happens when W is too small, what if DP yields a point outside the field, when to suppress the decimal point, and so on.)  Bartc 




Bartc 
Bartc
Guest
Posts: n/a

"pozz" <(EMail Removed)> wrote in message news:ihabfg$e2$(EMail Removed)... > Il 20/01/2011 18:24, Seebs ha scritto: >> [...] It did, however, >> look like a fairly arcane spec, and I'm still not sure what the intended >> functionality is. > > It is very simple. I'm using a basic 16bit microprocessor with limited > code memory. I don't want to use floating point variables, because they > are very time and size consuming. Your approach, using a signed integer plus (effectively) an exponent field, *is* floating point... However your 16+16bit format yields 15 bits of precision, plus a toobig exponent range, while normal 32bit floating point typically gives 23 bits of precision, and an 8bit exponent range. And combined in a way to make it easy to compare, assign and so on. The format also differs from yours, in that the 'integer' part is usually normalised to represent a number in the range 1.0 to 1.999999... Your format I believe would have multiple representations for numbers: (123,1) is 1230, but so is (1230,0). So using an established standard format (IEEE floating point) would have benefits, even if you don't do any actual floating point arithmetic on the numbers. (BTW if you don't care about the standard formats, but like to save memory, then 16+8bit format would work almost as well, if your microprocessor is byteaddressable,)  Bartc 




Bartc 
Seebs
Guest
Posts: n/a

On 20110120, pozz <(EMail Removed)> wrote:
> This is the reason why I use int variables to store the significant > digits of all the signals even with different resolutions. But I need to > know the resolution (divisor/multipler) together with the significant > digits to output a human readable value. > This is the reason to have a function that converts the couple (value, > div) in a formatted string. Makes sense! Hmm. /* printnum: print a string of digits into a buffer, * optionally with magnitude used as a fixedpoint * denominator. * magnitude is the log(10) of the number; thus, * 123, 1 => 1230 * 123, 0 => 123 * 123, 1 => 12.3 */ int printnum(char *buf, size_t size, int digits, int magnitude) { size_t chars; int i; chars = snprintf(buf, size, "%d", digits); if (chars > size) { fprintf(stderr, "Number too big.\n"); return 1; } if (magnitude > 0) { if (chars + magnitude > (size  1)) { fprintf(stderr, "Number plus multiplier too big.\n"); return 1; } for (i = 0; i < magnitude; ++i) buf[chars + i] = '0'; buf[chars + i] = '\0'; return 0; } else if (magnitude < 0) { magnitude *= 1; if (magnitude > chars) { if (magnitude + 1 > (size  1)) { fprintf(stderr, "No space for leading zeroes.\n"); return 1; } memmove(buf + 1 + (magnitude  chars), buf, chars + 1); buf[0] = '.'; for (i = 0; i < (magnitude  chars); ++i) buf[i + 1] = '0'; return 0; } else { if (chars + 1 > (size  1)) { fprintf(stderr, "No space for decimal.\n"); return 1; } memmove(buf + chars  magnitude + 1, buf + chars  magnitude, magnitude + 1); buf[chars  magnitude] = '.'; return 0; } } else { return 0; } } .... The rationale of this design is that it basically separates things into the question of what the digits are, and the question of where the decimal point goes. There's probably a prettier way to do this. I suppose you could handle negative magnitudes quite nicely with: int ten2the = 1; for (i = 0; i < magnitude; ++i) ten2the *= 10; printf("%d.%0*d", (digits / ten2the), magnitude, (digits % ten2the)); That might be saner. Anyway, there's a couple of ideas, maybe one of them will get you somewhere. s  Copyright 2010, all wrongs reversed. Peter Seebach / (EMail Removed) http://www.seebs.net/log/ < lawsuits, religion, and funny pictures http://en.wikipedia.org/wiki/Fair_Game_(Scientology) < get educated! I am not speaking for my employer, although they do rent some of my opinions. 




Seebs 
Ian Collins
Guest
Posts: n/a

On 01/21/11 05:45 PM, Seebs wrote:
> On 20110120, pozz<(EMail Removed)> wrote: >> This is the reason why I use int variables to store the significant >> digits of all the signals even with different resolutions. But I need to >> know the resolution (divisor/multipler) together with the significant >> digits to output a human readable value. > >> This is the reason to have a function that converts the couple (value, >> div) in a formatted string. > > Makes sense! Hmm. > > /* printnum: print a string of digits into a buffer, > * optionally with magnitude used as a fixedpoint > * denominator. > * magnitude is the log(10) of the number; thus, > * 123, 1 => 1230 > * 123, 0 => 123 > * 123, 1 => 12.3 > */ > int > printnum(char *buf, size_t size, int digits, int magnitude) { > size_t chars; > int i; > > chars = snprintf(buf, size, "%d", digits); > if (chars> size) { > fprintf(stderr, "Number too big.\n"); > return 1; > } > if (magnitude> 0) { > if (chars + magnitude> (size  1)) { > fprintf(stderr, "Number plus multiplier too big.\n"); > return 1; > } > for (i = 0; i< magnitude; ++i) > buf[chars + i] = '0'; > buf[chars + i] = '\0'; > return 0; > } else if (magnitude< 0) { > magnitude *= 1; > if (magnitude> chars) { > if (magnitude + 1> (size  1)) { > fprintf(stderr, "No space for leading zeroes.\n"); > return 1; > } > memmove(buf + 1 + (magnitude  chars), buf, chars + 1); > buf[0] = '.'; > for (i = 0; i< (magnitude  chars); ++i) > buf[i + 1] = '0'; > return 0; > } else { > if (chars + 1> (size  1)) { > fprintf(stderr, "No space for decimal.\n"); > return 1; > } > memmove(buf + chars  magnitude + 1, buf + chars  magnitude, magnitude + 1); > buf[chars  magnitude] = '.'; > return 0; > } > } else { > return 0; > } > } > > .... The rationale of this design is that it basically separates things into > the question of what the digits are, and the question of where the decimal > point goes. There's probably a prettier way to do this. I suppose you > could handle negative magnitudes quite nicely with: > > int ten2the = 1; > for (i = 0; i< magnitude; ++i) > ten2the *= 10; > printf("%d.%0*d", (digits / ten2the), magnitude, (digits % ten2the)); > > That might be saner. I tackled (without any library functions) this by first breaking down the format string into one of these: typedef struct format_t { const char* before; const char* after; int beforeSize; int afterSize; int width; char sign; char pad; } Format; Then formatting the number thus: char* formatNumber( int number, int exponent, const Format* format ) { static char str[16]; char* p = str+sizeof(str)1; *p = '\0'; const char* const end = p; if( exponent >= 0 ) { while( exponent ) *p = '0'; while( number ) { *p = '0'+(number%10); number /= 10; } } else /* negative exponent */ { while( number ) { *p = '0'+(number%10); number /= 10; if( ++exponent == 0 ) *p = '.'; } } return decorateNumber( p, end, format ); }  Ian Collins 




Ian Collins 
Bartc
Guest
Posts: n/a

"Bartc" <(EMail Removed)> wrote in message
news:ihahei$im9$(EMail Removed)september.org... > > "pozz" <(EMail Removed)> wrote in message > news:ihack6$1go$(EMail Removed)... > You're making things a little harder (IMO) by using the Cstyle format > specification for sprintfnum(). This is fiddly to decipher. > > Perhaps forget that to start with (it can be bolted on later), and > concentrate on the 3 parameters that the format would yield: > > Width, Leadingzeros, and Plussign (W,Z and P) How is one implementation that appears to work. Although your spec is rather ambiguous. It directly prints the number rather than return a string; and expects all the parameters (width, etc) to have been previously obtained (since I think that parsing the format string properly is actually a bigger task): #include <stdio.h> #include <stdlib.h> #include <string.h> void emit(char c) { printf("%c",c);} /* X is base number Dp (Div) is x10 scale index (2 1 0 1 2 => /100 /10 *1 *10 *100) Width is minimum width (no error if exceeded) Plus is 0, or 1 or '+' to force sign Zeropad is 1 to have leading zeros on left No decimal point unless dp is negative Output goes directly to stdout via emit() */ void formatnum(int x,int dp, int width,int plus,int zeropad) { int asign=0,bsign=0,padding=0; int zerodot=0,dotzeros=0,trailzeros=0,middot=0,xlen; char str[20]; int i,m; xlen=sprintf(str,"%d",abs(x)); if (x<0  (x>=0 && plus)) if (zeropad) asign=1; else bsign=1; if (dp>0) trailzeros=dp; else if (dp<0) { m=dp; if (m>=xlen) { zerodot=1; dotzeros=(mxlen); } else middot=m; } padding=width(zerodot*2+dotzeros+bsign+(middot?1:0)+xlen+trailz eros)asign; if (padding<0) padding=0; if (asign) emit(x<0?'':'+'); for (i=1; i<=padding; ++i) emit(zeropad?'0':' '); if (bsign) emit(x<0?'':'+'); if (zerodot) {emit('0'); emit('.');} for (i=1; i<=dotzeros; ++i) emit('0'); for (i=0; i<xlen; ++i) { emit(str[i]); if (middot && (xleni1==middot)) emit('.'); } for (i=1; i<=trailzeros; ++i) emit('0'); } int main(void){ char* s; int dp; for (dp=5; dp<5;++dp) { printf("<"); formatnum(123,dp, 10,0,0); printf(">\n"); } }  Bartc 




Bartc 
Bartc
Guest
Posts: n/a

"pozz" <(EMail Removed)> wrote in message news:ihibmb$rut$(EMail Removed)... > Il 20/01/2011 20:58, Bartc ha scritto: >> Your approach, using a signed integer plus (effectively) an exponent >> field, >> *is* floating point... > > Hmmm..., I think my approach is fixed point rather than floating point. > When I set the exponent of 10 (divisor or multiplier), the number is > fixedpoint. No. With fixed point, you don't store the exponent, divisor, multiplier or whatever you call it. The position of the decimal point is always in the same (fixed) place for values of the same fixed point type. As soon as you start adding a variable multiplier, then it becomes floating point (because the position of the decimal point is no longer fixed). > After reading Wikipedia article about fixed point, Then that should have made it clearer. > I understand this type of format has some reason in many cases, above all > in embedded applications where FPU is not present... and this is my case. > Also, the fixedpoint representation isn't affected by the problem of > representing fractional numbers (0.1, 0.01) without errors. With floating > point this is not possible. I think it is, assuming your fixed point repr still uses binary. I doubt from your op that you were using decimal or BCD format. Binary fixedpoint still has a problem with 0.1. Your original scheme is better for this purpose, as 0.1 is represented exactly by (1,1). (But we don't know what the source of your data is, how accurate or noisy it is, and whether these matters have any significance.) > Some software (like GNUCash) uses only fixedpoint variables to avoid the > problem of rounding. Assuming that uses a decimal format, there will always be errors; what does it store for 1/3? >> So using an established standard format (IEEE floating point) would have >> benefits, even if you don't do any actual floating point arithmetic on >> the >> numbers. > > Are you sure? Operations with floating point variables (even only the > assignment) is very timeconsuming on a lowend embedded processor without > the FPU. That sounds unlikely. Assigning 32bits should be independent on whether it's an int, a float, or comprises two shorts. *Especially* if there is no FPU which the compiler might try and use. > Also the compiler should include a relevant size library to manage > floating point variables. I did this stuff when I had no compiler help. The first floating point format I programmed used 24bits (1+7+16bit) on an 8bit microprocessor. That didn't even have integer multiply or divide, so there wasn't that great an advantage to using the inferior fixed point rather than floating point. And of course a lot of corners needed to be cut to get any sort of speed (no checking for underflow, overflow for example). It sounds like possibly your compiler is calling in a hefty library as soon as anything is declared as a float. Unless you want to program in assembler however, then the fixed point or scaled format you have might be the best bet. (Also, the IEEE format I suggested uses binary format, making scaling by powers of 10 diffcult  ie. slow  even when you do this in assembler. So forget that. Although it's not that clear now exactly what your representation is and whether it's binary or decimal). > Moreover, with floating point variables I can't store the simple number > 0.1. You can also store it as a string: "0.1", which is a kind of decimal format. > After thinking about fixedpoint arithmetic, I found that a fixedpoint > number is a "two integers" number: integer and decimal parts. > The fractional value 1.23 can be represented as > 123 with a scale of 100 (100 is the factor 1/100) > or as > 1 (integral part) and 23 (decimal part) > If I can convert the first representation in the second, it'll be very > simple to printout in a textual form the two parts. > > So I wrote this code: > whole = exp > 0 ? (long int)x * exp : x / exp; I thought you said you had a lowly 16bit processor. Divide is usually the slowest operation. With your original scheme, the 'exponent' merely involved counting along a string. > The first difference is that the divisor/multiplier is the real > divisor/multiplier (10, 100, 1000) and not only the exponent (1, 2, 3). Well if it's fast enough then that's probably OK.  Bartc 




Bartc 
pozz
Guest
Posts: n/a

On 23 Gen, 21:50, "Bartc" <(EMail Removed)> wrote:
> >> Your approach, using a signed integer plus (effectively) an exponent > >> field, > >> *is* floating point... > > > Hmmm..., I think my approach is fixed point rather than floating point. > > When I set the exponent of 10 (divisor or multiplier), the number is > > fixedpoint. > > No. With fixed point, you don't store the exponent, divisor, multiplier or > whatever you call it. The position of the decimal point is always in the > same (fixed) place for values of the same fixed point type. > > As soon as you start adding a variable multiplier, then it becomes floating > point (because the position of the decimal point is no longer fixed). Yes, you'd be right if I change the multiplier with arithmetic operations. In my application multiplier is stored in a variable, but it remains constant during execution. Suppose the multiplier is 1/100 (read from a non volatile memory): it will never change. When x=5678, the real value is 56.78. If multiply by 2, x will be 11356 and the real value will be 113.56. The decimal point always stays after the second digits (starting from the right). With floatingpoint representation, the multiplier will change accordingly with the operations (addition, multiplication and so on). > > I understand this type of format has some reason in many cases, above all > > in embedded applications where FPU is not present... and this is my case. > > Also, the fixedpoint representation isn't affected by the problem of > > representing fractional numbers (0.1, 0.01) without errors. With floating > > point this is not possible. > > I think it is, assuming your fixed point repr still uses binary. I doubt > from your op that you were using decimal or BCD format. Binary fixedpoint > still has a problem with 0.1. > > Your original scheme is better for this purpose, as 0.1 is represented > exactly by (1,1). (But we don't know what the source of your data is, how > accurate or noisy it is, and whether these matters have any significance.) My representation is binary of course, but the multiplier is base 10, not base 2. > >> So using an established standard format (IEEE floating point) would have > >> benefits, even if you don't do any actual floating point arithmetic on > >> the > >> numbers. > > > Are you sure? Operations with floating point variables (even only the > > assignment) is very timeconsuming on a lowend embedded processor without > > the FPU. > > That sounds unlikely. Assigning 32bits should be independent on whether > it's an int, a float, or comprises two shorts. *Especially* if there is no > FPU which the compiler might try and use. Ok, it is time consuming only for operations, like sprintf("%f"). > > Also the compiler should include a relevant size library to manage > > floating point variables. > > I did this stuff when I had no compiler help. The first floating point > format I programmed used 24bits (1+7+16bit) on an 8bit microprocessor. > That didn't even have integer multiply or divide, so there wasn't that great > an advantage to using the inferior fixed point rather than floating point. > > And of course a lot of corners needed to be cut to get any sort of speed (no > checking for underflow, overflow for example). The compiler I'm using has almost full support for floating point variables. So I think I'd use it without writing myself library code for floating point. > It sounds like possibly your compiler is calling in a hefty library as soon > as anything is declared as a float. Unless you want to program in assembler > however, then the fixed point or scaled format you have might be the best > bet. Yes, you got it. > (Also, the IEEE format I suggested uses binary format, making scaling by > powers of 10 diffcult  ie. slow  even when you do this in assembler. So > forget that. Although it's not that clear now exactly what your > representation is and whether it's binary or decimal). It is binary, with multiplier base 10, not base 2. So 10.2 is 102 with multiplier 1/10. > > Moreover, with floating point variables I can't store the simple number > > 0.1. > > You can also store it as a string: "0.1", which is a kind of decimal format. Actually I have (1,1/10) and I can't change it. So I need a way to convert it in a textual form. > > So I wrote this code: > > whole = exp > 0 ? (long int)x * exp : x / exp; > > I thought you said you had a lowly 16bit processor. Divide is usually the > slowest operation. > > With your original scheme, the 'exponent' merely involved counting along a > string. Yes, I know. Anyway, as you said in another message, sprintf() uses divisions by 10 if you have binary values (like me). So this is another division that simplify the algorithm. I'll measure some benchmarks. 




pozz 


 
Thread Tools  


Similar Threads  
Thread  Thread Starter  Forum  Replies  Last Post 
way way way OT: MCNGP Announcement  Neil  MCSE  174  04172006 05:55 PM 
AMD Opteron: 1way, 2way, ... Up to 8way.  John John  Windows 64bit  12  12272005 08:17 AM 
OT: Number Nine, Number Nine, Number Nine  Frisbee®  MCSE  37  09262005 04:06 PM 
TURNING CRAZY, is there a way to write it in a different way? whats wrong  francisco lopez  Javascript  2  12312004 11:15 PM 
Need formatting options menu for formatting hard drive  Mark T.  Computer Support  3  11242003 11:50 PM 
Powered by vBulletin®. Copyright ©2000  2014, vBulletin Solutions, Inc..
SEO by vBSEO ©2010, Crawlability, Inc. 