根据常识,什么是正确的: (int) blabla * 255.99999999999997 或 round(blabla*255)?

2024-02-04

最近我在 webkit 源代码中发现了这个有趣的事情,与颜色转换(hsl 到 rgb)相关:

http://osxr.org/android/source/external/webkit/Source/WebCore/platform/graphics/Color.cpp#0111 http://osxr.org/android/source/external/webkit/Source/WebCore/platform/graphics/Color.cpp#0111

const double scaleFactor = nextafter(256.0, 0.0); // it's here something like 255.99999999999997
// .. some code skipped
return makeRGBA(static_cast<int>(calcSomethingFrom0To1(blablabla) * scaleFactor), 

我在这里找到的也一样:http://www.filewatcher.com/p/kdegraphics-4.6.0.tar.bz2.5101406/kdegraphics-4.6.0/kolourpaint/imagelib/effects/kpEffectHSV.cpp.html http://www.filewatcher.com/p/kdegraphics-4.6.0.tar.bz2.5101406/kdegraphics-4.6.0/kolourpaint/imagelib/effects/kpEffectHSV.cpp.html

(int)(value * 255.999999)

使用这种技术到底正确吗?为什么不直接使用像 round(blabla * 255) 这样的东西? 是C/C++的特性吗?正如我所见,严格来说,在 100 种情况中,有 27 种情况会返回并不总是正确的结果。请参阅电子表格:https://docs.google.com/spreadsheets/d/1AbGnRgSp_5FCKAeNrELPJ5j9zON9HLiHoHC870PwdMc/edit?usp=sharing https://docs.google.com/spreadsheets/d/1AbGnRgSp_5FCKAeNrELPJ5j9zON9HLiHoHC870PwdMc/edit?usp=sharing

请有人解释一下——我认为这应该是一些基本的东西。


通常我们想要映射一个真实的值x在(闭)区间内[0,1]为整数值j在范围中[0 ...255].

我们希望以“公平”的方式做到这一点,这样,如果实数在范围内均匀分布,则离散值将近似等概率:256 个离散值中的每一个都应获得“相同的份额”(1/ 256)从[0,1]间隔。也就是说,我们想要一个像这样的映射:

[0    , 1/256) -> 0
[1/256, 2/256) -> 1 
...
[254/256, 255/256) -> 254
[255/256, 1]       -> 255

我们不太关心过渡点 [*],但我们确实希望覆盖整个范围 [0,1]。如何做到这一点?

如果我们简单地这样做j = (int)(x *255):值 255 几乎不会出现(仅当x=1);和其余的值0...254每个人都会获得间隔的 1/255。这将是不公平的,不管限制点处的舍入行为。

如果我们这样做j = (int)(x * 256):这个分区是公平的,除了一个问题:我们会得到值 256(超出范围!)x=1 [**]

这就是为什么j = (int)(x * 255.9999...) (where 255.9999...实际上是小于 256 的最大双精度)就可以了。

另一种实现(也是合理的,几乎等效)是

j = (int)(x * 256); 
if(j == 256)  j = 255;  
// j = x == 1.0 ? 255 : (int)(x * 256); // alternative

但这会更加笨拙并且可能效率较低。

round()在这里没有帮助。例如,j = (int)round(x * 255)会给整数 1/255 的份额j=1...254以及该值的一半到极值点j=0, j=255.

[*] 我的意思是:我们对“小”邻域(例如 3/256)中发生的情况并不是非常感兴趣:四舍五入可能会得到 2 或 3,这并不重要。但我们对极值感兴趣:我们想要得到 0 和 255,因为x=0 and x=1分别。

[**] IEEE 浮点标准保证这里没有舍入歧义:整数承认精确的浮点表示,乘积将是精确的,并且转换将始终给出 256。此外,我们保证1.0 * z = z.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

根据常识,什么是正确的: (int) blabla * 255.99999999999997 或 round(blabla*255)? 的相关文章

随机推荐

  • PID和TID的区别

    PID和TID有什么区别 标准答案是 PID 用于进程 而 TID 用于线程 然而 我发现有些命令可以互换使用它们 例如 htop有一个 PID 列 其中显示同一进程的线程的 PID 具有不同的值 那么PID什么时候代表线程或进程呢 这很复
  • 如何检测IE6,并显示警报?

    我试图在使用 IE6 的用户使用我的网站时显示警报 我想这样的事情会起作用 我会对此进行测试 但我没有可以使用 ATM 的 Windows 盒子 这是正确的方法吗 是的 这有效 当然 你可以使用像这样的东西 http code google
  • 如何解析 XML 并获取特定节点属性的实例?

    我在 XML 中有很多行 并且正在尝试获取特定节点属性的实例
  • 如何使 Eclipse Formatter 不破坏注释掉的代码?

    我的很多同事喜欢留下注释掉的代码 以及如何使 Eclipse Formatter 不破坏该代码的格式 现在它会生成一个大斑点或块 附 我知道我可以以某种方式配置格式化程序以忽略该代码 我做过一次 但我不记得如何做 在 Eclipse 格式化
  • 使用 Python 通过 Mailgun 提交变量时出错

    我正在尝试使用 Python 通过 Mailgun 发送邮件 在这种情况下 我正在尝试将变量推到旁边 我的代码如下 requests post MailGun URL auth api api key data from From Mail
  • 使用 Cx_freeze 或 Py2Exe 打包 Scrapy 应用程序

    我正在尝试打包一个网络抓取脚本 使用 scrapy 构建 作为独立应用程序运行 供我的老板使用 我使用 Tkinter 构建了一个小型桌面 GUI 它通过 os system 调用来调用我的 Scrapy 蜘蛛 我当前的构建实现 使用 cx
  • VHDL 中的 BRAM_INIT

    我正在模拟基于处理器的设计 其中程序存储器内容保存在 BRAM 中 我正在使用 VHDL 推断 BRAM 实现程序存储器 我试图避免使用 CoreGen 因为我想保持设计的可移植性 最终该设计将进入 FPGA 我想看看是否有一种方法可以使用
  • 如何集成Pygame和PyQt4?

    我正在使用 python 2 7 和 Ubuntu 14 04 我正在尝试做this http www pygame org docs ref display html pygame display init为了让我的 pygame 窗口位
  • 从源文件中删除所有注释(单行/多行)和空行[重复]

    这个问题在这里已经有答案了 如何从 C 源文件中删除所有注释和空行 请记住 可能存在嵌套注释 一些例子 string text not a comment a comment multiline comment string newText
  • 在脸部周围绘制精美的矩形

    我使用以下代码来检测脸部并在脸部顶部绘制矩形 while True get video frame ret img cap read input img cv2 cvtColor img cv2 COLOR BGR2RGB img h im
  • MvvmCross - 如何将 UIView.Layer.AnyProperty (Xamarin.iOS) 绑定到视图模型上的属性?

    我在视图模型上有一个名为 BorderColor 的字符串类型的属性 我尝试将其绑定到 UIView Layer BorderColor 这是绑定语法 set Bind this MyUIView For Layer BorderColor
  • Xcode 源自动格式化

    As a C developer I have become highly dependent on the automatic formatting in Visual Studio 2008 Specifically I will us
  • 从 mysql_connect() 获取 PHP PDO 连接?

    我有一个旧版 PHP MySQL 应用程序调用 mysql connect 大量现有的下游代码使得mysql query 使用此连接直接或通过包装器进行调用 对于我在应用程序上开发的新代码 我想开始使用 PDO 如果我使用相同的主机 用户
  • “DataLoader”对象不支持索引

    我已经通过此 pytorch api 通过设置 download True 下载了 ImageNet 数据集 但我无法迭代数据加载器 错误显示 DataLoader 对象不支持索引 trainset torch utils data Dat
  • 调用mapViewDidFailLoadingMap委托方法时出现错误== 0

    在我的视图控制器中 我创建了一个 MKMapView 对象 我将委托设置为 self 并在 ViewController 中实现 void mapViewDidFailLoadingMap MKMapView mapView withErr
  • Spring data - 根据先前的插入插入数据

    我需要将数据保存到两个表中 一个实体和一个关联表 我只是用以下命令保存我的实体save 我的实体存储库中的方法 然后 为了性能 我需要将行插入到关联表中原生sql 这些行有我之前保存的实体的引用 问题来了 我得到一个完整性约束异常关于外键
  • jQuery - 窗口焦点、模糊事件未触发 - 适用于 Firefox 和 Chrome

    简而言之 我编写了一个简单的聊天应用程序供我和我的朋友使用 当运行应用程序的窗口没有焦点 最小化或位于其他窗口后面 并且出现消息时 我想更改窗口标题栏以充当警报 就像 Google 的聊天应用程序在 GMail 中所做的那样 在 Firef
  • 如何在 Phpunit 的静态提供程序中创建测试双打?

    Phpunit 10 已弃用非静态测试提供程序 这使得在提供者内部创建测试替身成为问题 因为像这样的方法createMock or createStub 不是静态的 这是一个演示该问题的假测试 public function provide
  • 在单独的线程中执行操作以解锁 UI

    我有一个用于生成报告的表格 我们正在使用RDLC报告并且报告被加载到aspx page 所以这是代码Form 表单目标设置为 blank 并在新选项卡中打开 using Html BeginForm AssetReports AssetRe
  • 根据常识,什么是正确的: (int) blabla * 255.99999999999997 或 round(blabla*255)?

    最近我在 webkit 源代码中发现了这个有趣的事情 与颜色转换 hsl 到 rgb 相关 http osxr org android source external webkit Source WebCore platform graph