编写一个函数,要求用指针的方式实现传入的两个浮点数进行相加和相减,并输出加减的结果,在主程序中调用

编写一个函数,要求用指针的方式实现传入的两个浮点数进行相加和相减,并输出加减的结果,在主程序中调用,第1张

#include <stdioh>
void fun(float a,float b)
{
    float i,j;
    i=a+b;
    j=a-b;
    a=i;
    b=j;    
}
int main()
{
    float a,b;
    scanf("%f%f",&a,&b);
    fun(&a,&b);
    printf("相加:%f\n相减:%f\n",a,b);
    return 0;
}

关于js小数计算问题是js本身的问题。

如果想规避这个问题,可以在网上找一下对应的解决版本,或是自己编写相应的程序。

尽量不要用js原生的计算方法。

下面举几个问题的例子:

01+02=030000000000000004
452100=45199999999999994

实现方式有很多种,如果说不考虑兼容性,可以用toFix()

如果考虑兼容性,那就字符串截取,或是Math函数了。

最简单的就是先把01和02换成别的数字(因为在js中只有这两个数相加有bug,例如:11+12不会有问题),所以先让01和02分别乘以10,求和之后再除以10 ,则不会有问题:

可能很多小伙伴都忘记了js的Number对象有一个保留小数位数的方法:toFixed();传入一个需要保留的位数就OK:

因为toFixed方法返回的是一个字符串,所以别忘了把字符串转回浮点数

计算机内部如何表示数
我们都知道,计算机用位来储存及处理数据。每一个二进制数(二进制串)都一一对应一个十进制数。

这里以十进制数13来展示“按位计数法”如何表示整数:

十进制值 进制 按位格式 描述
13 10 13 1x10^1 + 3x10^0 = 10 + 3
13 2 1101 1x2^3 + 1x2^2 + 0x2^1 + 1x2^0 = 8 + 4 + 0 + 1

十进制值 进制 按位格式 描述
0625 10 0625 6x10^-1 + 2x10^-2 + 5x10^-3 = 06 + 002 + 0005
0625 2 0101 1x2^-1 + 0 x2^-2 + 1x2^-3 = 1/2 + 0 + 1/8

十进制整数转二进制方法:除2取余;十进制小数转二进制方法:乘2除整

十进制01转换成二进制,乘2取整过程:

01 2 = 02 # 0
02 2 = 04 # 0
04 2 = 08 # 0
08 2 = 16 # 1
06 2 = 12 # 1
02 2 = 04 # 0

从上面可以看出,01的二进制格式是:00001100011。这是一个二进制无限循环小数,但计算机内存有限,我们不能用储存所有的小数位数。那么在精度与内存间如何取舍呢?

有误差的两个数,其计算的结果,当然就很可能与我们期望的不一样了。注意前面的这句话中的“很可能”这三个字?为啥是很可能昵?

01 + 01 为什么等于02
答案是:两个有舍入误差的值在求和时,相互抵消了,但这种“负负得正,相互抵消”不一定是可靠的,当这两个数字是用不同长度数位来表示的浮点数时,舍入误差可能不会相互抵消。

又如,对于 01 + 03 ,结果其实并不是04,但04是最接近真实结果的数,比其它任何浮点数都更接近。许多语言也就直接显示结果为04了,而不展示一个浮点数的真实结果了。

另外要注意,二进制能精确地表示位数有限且分母是2的倍数的小数,比如05,05在计算机内部就没有舍入误差。所以05 + 05 === 1

计算机这样胡乱舍入,能满足所有的计算需求吗
我们看两个现实的场景:

对于一个修建铁路的工程师而言,10米宽,还是100001米宽并没有什么不同。铁路工程师就不需要这么高0x这样的精度
对于芯片设计师,00001米就会是一个巨大不同,他也永远不用处理超过01米距离
不同行业,要求的精度不是线性的,我们允许(对结果无关紧要的)误差存在。100001与10001在铁路工程师看来都是合格的。

虽然允许误差存在,但程序员在使用浮点数进行计算或逻辑处理时,不注意,就可能出问题。记住,永远不要直接比较两个浮点的大小:

你的这个问题貌似连续问了好几天,也问了好几个了,难道一直都没有解决的吗?

如果你一直都没有理解的话,那么我来给你仔细地讲一讲。

首先我们来看一段JS代码:

var a = 50050;
var b = 697;
var result = ab;
alert(result);

那么,我们alert之后的结果是:

34884849999999997

为什么这样?

网上有网友说,这是JavaScript的浮点数运算BUG,其实,并不能算是BUG,而是由于浮点数计算精度造成的误差;

这样一来,你所说的结果为3488485,对于JavaScript来说,就不准确了。

然后我们再来看下面的代码:

var a = 50050;
var b = 697;
var c = ab;    //这里的ab其实是34884849999999997
var result = Mathround(c100)/100; //那么它乘以100之后是34884849999999997
                                    //然后,取整后是348848,除100后是348848
alert(result); //结果自然就是348848

输出:

348848

好的,到这里相信你已经知道它产生的原因了,如果你想更细化地知道它为什么会出现那么多的小数位,可以看这篇文章的相关介绍:

float浮点数的二进制存储方式及转换>

那么接下来,看看如何解决这个问题:

我们知道,问题是出在了二进制数据计算和保存的过程之中,那么,我们就要在它进行计算和保存之前,对其进行处理,

如何处理呢?我们已经知道最初参与计算的两位浮点数都是两位小数,同时我们还需要以两位小数后面的一位小数来决定是否四舍五入,这样,我们将其中一个浮点数的小数点后移3位,这样能够让我们获取到的结果保持在我们需要的小数位后3位都在整数部分,也就不存在浮点数BUG的问题了:

var a = 500501000; //让其中一个参与运算的浮点数小数点后移3位
var b = 697;
var c = ab/1000; //计算完成后,再前移三位
alert(c); //我们得到的中间值结果准确!
var result = Mathround(c100)/100; //再参与四舍五入计算
alert(result); //结果准确

输出结果 :

348849

另外,像这样在JavaScript下计算浮点数的过程由于经常会出现这种不可控的现象,所以,聪明的程序工程师们写了很多规避这种不可控现象的函数,下面就给你提供一些这方面的资料:

js浮点数精确计算函数(加,减,乘,除) >

JS浮点数运算Bug的解决办法 >

——————

最后我想说的是,我这几天混迹于百度知道,至少看你问过这个问题四遍了,也就是说,这个问题是我看到的你的第四个相同的问题。

而你在其它几个问题里,并不是没有得到答案,而那几个问题回答的答案也相对比较明确了。

你所要求的:“不要什么公式”、“简单的”等要求,是有的,粘贴复制就可以了,把他们提供的方法粘贴到你的代码上,调用就可以了。

但这样好像还无法满足你,让我们这些为此兢兢业业,试图解决各种有挑战性问题的网友和程序员们情何以堪呐!

我真想写几K的文档,就建完了一个站,但它不现实不是


欢迎分享,转载请注明来源:内存溢出

原文地址: http://www.outofmemory.cn/yw/13368251.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-07-23
下一篇 2023-07-23

发表评论

登录后才能评论

评论列表(0条)

保存