Extracting individual digits from a float

佐手、 提交于 2020-01-24 15:47:29

问题


I have been banging my head on this one all day. The C++ project I am currently working on has a requirement to display an editable value. The currently selected digit displays the incremented value above and decremented value below for said digit. It is useful to be able to reference the editable value as both a number and collection of digits. What would be awesome is if there was some indexable form of a floating point number, but I have been unable to find such a solution. I am throwing this question out there to see if there is something obvious I am missing or if I should just roll my own.


Thanks for the advice! I was hoping for a solution that wouldn't convert from float -> string -> int, but I think that is the best way to get away from floating point quantization issues. I ended up going with boost::format and just referencing the individual characters of the string. I can't see that being a huge performance difference compared to using combinations of modf and fmod to attempt to get a digit out of a float (It probably does just that behind the scenes, only more robustly than my implementation).


回答1:


Internal representation of the float point numbers aren't like was you see. You can only cast to a stirng.

To cast, do this:

char string[99];
sprintf(string,"%f",floatValue);

Or see this : http://www.parashift.com/c++-faq-lite/misc-technical-issues.html#faq-39.1

The wikipedia article can explain more on the representation: http://en.wikipedia.org/wiki/Floating_point




回答2:


Oh, there are many ways to convert to a string. (Though I do prefer snprintf() myself.)

Or you could convert to an int and pull the digits out with modulus and integer-division. You can count the number of digits with log{base10}.

(Remember: log{baseA}_X / log{baseA}_B = log{baseB}_X.)

Example:

#define SHOW(X) cout << # X " = " << (X) << endl

int
main()
{
  double d = 1234.567;

  SHOW( (int(d)%10000) / 1000 );
  SHOW( (int(d)%1000)  / 100  );
  SHOW( (int(d)%100)   / 10   );
  SHOW( (int(d)%10)           );
  SHOW( (int(d*10)  % 10)     );
  SHOW( (int(d*100) % 10)     );
  SHOW( (int(d*1000)% 10)     );

  SHOW( log(d)/log(10) );
}

Though you ought to use static_cast...

Watch out for exponential notation. With a very big or very small numbers, you may have a problem.

Floating point numbers also have round off issues that may cause you some grief. (It's the same reason why we don't use operator== between two doubles. Or why you can't rely on a*b == b*a. Depending on the exact values of a & b, they may differ very slightly out around 10^-25.)




回答3:


You can cast between string and float only by using boost::lexical_cast. However, you can't directly index the float form - it's internally not stored as decimal digits. This is probably not that much of an issue. For your UI, you will most likely keep a string form of the number anyway, with conversions to and from float in the getter/setter.



来源:https://stackoverflow.com/questions/339150/extracting-individual-digits-from-a-float

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!