-6

I need a method to return the firsts non zero numbers from a double in the following way: Any number >= 1 or == 0 will return the same; All the rest will return as per the following examples: (Please note that I am using double because the potential imprecision is irrelevant in the use case whereas saving memory is relevant).

double NumberA = 123.2; // Returns 123.2
double NumberB = 1.2; // Returns 1.2
double NumberC = 0.000034; // Returns 3.4
double NumberD = 0.3; // Returns 3.0
double NumberE = -0.00000087; // Returns -8.7

Roblogic
  • 107
  • 3
  • 8
  • 2
    And what have you tried so far? Or what are your thoughts about how to achieve it? – Astrid E. Aug 30 '22 at 16:20
  • 1
    You may start by writing tests out of your examples, then try to implement logic which satisfies the tests. – Renat Aug 30 '22 at 16:22
  • You don't need such a method at all because leading zeroes aren't significant. There's no difference between `3.0` and `03.0`. The bits stored in RAM are exactly the same. You'd never get the results you posted either, unless you tried to convert those doubles to strings and parse them back using different separators each time – Panagiotis Kanavos Aug 30 '22 at 16:22
  • I didn't downvote, but what you claim simply isn't true and proving this is as simple as `Trase.Assert(NumberD==0.3d)`. Somehow, somewhere, you're using string manipulations to mangle the values – Panagiotis Kanavos Aug 30 '22 at 16:23
  • @SadlyFullStack the only way to get the claimed results is to mangle the numbers by converting them to strings. `double NumberD = 0.3;` will *never* produce `3.0`. If it did, hundreds of thousands of .NET developers would have noticed 20 years ago. Problems like this are caused by attempting to "fix" imagined bugs, like replacing `,` with `.` or removing `.`. – Panagiotis Kanavos Aug 30 '22 at 16:30
  • 4
    @PanagiotisKanavos I believe the comment on each line describes what Roblogic _wants_ some method to return for the specific `double` value, not what they actually have. – Astrid E. Aug 30 '22 at 16:31
  • @AstridE. that's *completely* different from what the question says and any kind of logic – Panagiotis Kanavos Aug 30 '22 at 16:31
  • 3
    This sounds like an [XY problem](https://meta.stackexchange.com/questions/66377/what-is-the-xy-problem). Why do you want to do this? What should happen if the value is `0`? – Joe Sewell Aug 30 '22 at 16:32
  • @PanagiotisKanavos [Edit: I am not saying it is logical, but] I am simply trying to interpret the first line: _I need a method to return the firsts non zero numbers from a double in the following way:_ – Astrid E. Aug 30 '22 at 16:32
  • 2
    @PanagiotisKanavos The phrase "*I need a method to return the firsts non zero numbers from a double in the following way:*" indicates that what comes after are the results they're trying to produce, not what they're currently producing. I have a hard time seeing how that's not a logical conclusion – Jesse Aug 30 '22 at 16:33
  • That should be digits then, not numbers. I'm not the only one confused. I'm the only one who didn't downvote yet – Panagiotis Kanavos Aug 30 '22 at 16:34
  • 1
    The question is not well-defined. Why not use strings? They are not evil, in fact they a all your eyes can see.. And anythinf 'financial' shoudl work only with the decimal (ie money) type!! – TaW Aug 30 '22 at 16:59
  • Side note: @Roblogic there no such thing as 0.3d... Please re-read https://stackoverflow.com/questions/588004/is-floating-point-math-broken more carefully. – Alexei Levenkov Aug 30 '22 at 17:11
  • 1
    @AstridE. please re-read https://meta.stackoverflow.com/questions/357436/why-isnt-it-required-to-provide-comments-feedback-for-downvotes-and-why-are-pr and if you have *new* reasoning post on meta. – Alexei Levenkov Aug 30 '22 at 17:14

2 Answers2

3

One option would be to iteratively multiply by 10 until you get a number greater than 1:

public double RemoveLeadingZeros(double num)
{
    if (num == 0) return 0; 
    while(Math.Abs(num) < 1) { num *= 10};
    return num;
}

a more direct, but less intuitive, way using logarithms:

public double RemoveLeadingZeros(double num)
{
    if (num == 0) return 0; 
    if (Math.Abs(num) < 1) {
        double pow = Math.Floor(Math.Log10(num));
        double scale = Math.Pow(10, -pow); 
        num = num * scale;
    }
    return num;
}

it's the same idea, but multiplying by a power of 10 rather then multiplying several times.

Note that double arithmetic is not always precise; you may end up with something like 3.40000000001 or 3.3999999999. If you want consistent decimal representation then you can use decimal instead, or string manipulation.

D Stanley
  • 149,601
  • 11
  • 178
  • 240
  • That's still not enough, because `0.3` becomes `3.0` and `0.00034` becomes `3.4`. The full logic is till missing from the question – Panagiotis Kanavos Aug 30 '22 at 16:37
  • 2
    @PanagiotisKanavos That seems to be what the OP is looking for, based on the expected return value (input: 0.3, output: 3.0, etc.) . – D Stanley Aug 30 '22 at 16:45
  • @D Stanley Thanks. Have to try this but it seems what I needed! – Roblogic Aug 30 '22 at 16:50
  • 4
    @Roblogic, just an FYI and with respect to your comment underneath your own question, where you mentioned "_working with financial algorithms_". Unless you already considered this yourself, in that case i would strongly suggest to heed the suggestion given in the answer about using `decimal` instead of floating point types like float/double, as i think the last thing one would need in their financial calculations are imprecisions introduced by floating point arithmetic. –  Aug 30 '22 at 16:53
  • I'm pretty sure that multiplying by 10 ( = 2*5) will disturb at least some digits in the number as it is not power of 2... I'd probably go with manual slicing of the bits. (Indeed as @MySkullCaveIsADarkPlace said it does not matter for financial calculations as those done with `decimal`) – Alexei Levenkov Aug 30 '22 at 17:04
  • @MySkullCaveIsADarkPlace I understand and appreciate your suggestion but for futures instruments the trading platforms use double. I guess as most numbers are rounded to the nearest tick size. – Roblogic Aug 30 '22 at 17:32
  • @D Stanley The first method does exactly what I needed. Thank you!. The second one, what is "x"? it does not compile. – Roblogic Aug 31 '22 at 10:30
  • @D Stanley Thanks. Very creative indeed! – Roblogic Aug 31 '22 at 21:58
-3

I would start with converting to a string. Something like this:

string doubleString = NumberC.ToString();

I don't know exactly what this will output, you will have to check. But if for example it is "0.000034" you can easily manipulate the string to meet your needs.

Joe
  • 212
  • 2
  • 11
  • The problem was *caused* because the OP converted to a string without saying so – Panagiotis Kanavos Aug 30 '22 at 16:29
  • 1
    @PanagiotisKanavos, no the OP didn't mangle anything. They _want_ to remove any significant zeros from any number between [-1,1] and move the decimal dot behind the first non-zero digit. They _want_ to change the value of these numbers. –  Aug 30 '22 at 16:31
  • @MySkullCaveIsADarkPlace there are 3 others that didn't read it like this and downvoted. The OP talks about numbers, not digits. That's still NOT what the OP wants though, because *some* digits are treated as decimals and some aren't . `0.3` becomes `3.0` but `0.000034` becomes `3.4`. Why?? – Panagiotis Kanavos Aug 30 '22 at 16:36
  • 2
    @PanagiotisKanavos, the examples you just gave correlate perfectly with what i laid out in my previous comment. Unless you want to point out something that i somehow fail to see... –  Aug 30 '22 at 16:39