简体   繁体   English

删除十进制 C++ 后的尾随零

[英]Remove Trailing Zeros After Decimal C++

I have been trying to do a very easy thing and it's taking me hours.我一直在尝试做一件非常简单的事情,这需要我几个小时。 I can't seem to find a good answer to this question.我似乎找不到这个问题的好答案。

I have various numbers, I need to keep only up until the third digit after the decimal.我有各种各样的数字,我只需要保持到小数点后的第三位。 But, if there are trailing zero on the right, remove them.但是,如果右侧有尾随零,请将其删除。 For example:例如:

0.015356 -> 0.015
0.015000 -> 0.015
0.010320 -> 0.01
0.000320 -> 0

I have the numbers as float/double.我的数字是浮点数/双精度数。 I need to pass them into another function which will then print them.我需要将它们传递给另一个 function 然后打印它们。 I don't have control over the other function.我无法控制其他 function。 I can pass either numbers or strings, and they will get printed accordingly.我可以传递数字或字符串,它们会被相应地打印出来。

I suppose I need to pass on a string, cause otherwise it can't be achved?我想我需要传递一个字符串,否则无法实现?

I was able to remove the digits up until the third:我能够删除数字直到第三个:

num = floor(num*1000)/1000;
0.015356 -> 0.015000
0.000320 -> 0.000000

But now I have the problem of the trailing zero.但是现在我遇到了尾随零的问题。

In short, how can I achieve what I need?简而言之,我怎样才能实现我所需要的?

Is something like this what you are after?像这样的东西是你所追求的吗?

#include <iostream>
#include <sstream>
#include <iomanip>
#include <string>
#include <math.h>


std::string To_String_With_Decimal_Precision( double value, int decimals )
{
    std::ostringstream ss;
    ss << std::fixed << std::setprecision(decimals) << value;
    std::string s = ss.str();
    if(decimals > 0 && s[s.find_last_not_of('0')] == '.') {
        s.erase(s.size() - decimals + 1);
    }
    return s;
}


int main()
{

    double number = 0.015356;

    //Round to 3d.p
    number = floor(number*1000)/1000;


    std::cout << number << std::endl;
    std::cout << To_String_With_Decimal_Precision(number, 3);


    return 0;
}

Output: Output:

0.015
0.015

To be honest, i'm not sure why number = floor(number*1000)/1000;老实说,我不确定为什么number = floor(number*1000)/1000; made the number equal to 0.015 without the trailing zeros, but if that line doesn't work when you compile the code, use To_String_With_Decimal_Precision it should work with any level of decimal precision使数字等于 0.015 没有尾随零,但是如果在编译代码时该行不起作用,请使用To_String_With_Decimal_Precision它应该适用于任何级别的小数精度

how about a routine that determines the precision value case by case which can then be utilized in setprecision: Here is one design but because it operates on a native float, precision errors abound.一个例程如何确定精度值,然后可以在 setprecision 中使用:这是一种设计,但由于它在本机浮点数上运行,精度错误比比皆是。 Try the commented code without the parentheses with the input 0.011 to start to see why.尝试使用输入 0.011 的不带括号的注释代码开始了解原因。 For something more robust, consider designing an alternative algorithm similar to this that parses the string and work on the components;对于更健壮的东西,请考虑设计一种类似于此的替代算法来解析字符串并处理组件; alternatively, use a multiprecision library.或者,使用多精度库。

// a truthy zerotest indicates that there is a zero at the place of interest
// inputs                              process                           outputs
// value                               represent as mega value           precision up to
//                                     zerotest thousandths              
//                                     [t]prec=2 "don't want zero        3 decimals
//                                      zerotest hundredths
//                                      [t]prec=1
//                                       zerotest tenths
//                                       [t]prec=0
std::streamsize // setprecision takes a std::streamsize, prob aliased to long long
precision_cutoff_at_zero_for(double const input)
{
    int const inputMega = input *1000; // cast to int to discard decimals beyond 3
// WARNING float arithmetic e.g. input * 1000 is bad bad bad
// alt = input * (10.0*10.0*10.0) works but easy to forget parentheses losing precision
    int precisionRelative = 3; // assume not evenly divisible by 10 (first case)

    if (inputMega % 10 == 0) // evenly divisible by 10 (zerotest thousandth place)
    {
        --precisionRelative;
        if (inputMega % 100 == 0) // 0 at far right, followed by another to the left?
        {
            --precisionRelative;
            if (inputMega % 1000 == 0)
            {
                --precisionRelative; // etc
            }
        }
    }

    return precisionRelative;
}

then from main然后从主要

// the number is stored in valueDouble and the case specific precision is returned from the routine defined above
std::cout << std::fixed << std::setprecision(precision_cutoff_at_zero_for(valueDouble)) << valueDouble << "\n";

If you don't have control over the function, then you probably have no control over the stream that is used for the output in there.如果您无法控制 function,那么您可能无法控制用于 output 的 stream。 If this is the case, then the proper way is to pass the number as a string and generate the string on your own.如果是这种情况,那么正确的方法是将数字作为字符串传递并自行生成字符串。 A simple version could work as follows:一个简单的版本可以按如下方式工作:

#include <sstream>

int main() {

    double f = 0.015356;
    std::stringstream result;
    result << "0.";
    for (int mask = 10; mask <= 1000; mask*=10) {
        int digit = ((int)(f * mask))%10;
        result << digit;
    }
    
    std::cout << result.str();
 }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM